Created version for 17.01.

git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@1789 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
eiffel-org
2017-03-10 08:53:03 +00:00
parent 65b7ae1274
commit cb0518b8e1
2887 changed files with 59843 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,3 @@
title=LogoDefinition
author=halw
path=content/logodefinition

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,3 @@
title=LogoBeta
author=halw
path=content/logobeta

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,3 @@
title=LogoUpdateNeeded
author=halw
path=content/logoupdateneeded

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,3 @@
title=LogoReviewRequested
author=halw
path=content/logoreviewrequested

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,3 @@
title=LogoRule
author=halw
path=content/logorule

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,3 @@
title=LogoConstruction
author=admin
path=content/logoconstruction

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,3 @@
title=LogoInformation
author=admin
path=content/logoinformation

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 B

View File

@@ -0,0 +1,3 @@
title=LogoRecommended
author=admin
path=content/logorecommended

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,3 @@
title=LogoWarning
author=admin
path=content/logowarning

View File

@@ -0,0 +1,116 @@
[[Property:title|Community]]
[[Property:description|Members of the Eiffel community can contribute to this documentation through this book]]
[[Property:weight|15]]
[[Property:uuid|75c75712-7c3e-2757-51b7-77b404471e2e]]
=You can become a contributor!=
Eiffel is a community. Members of the Eiffel community can contribute to this documentation through this book.
EiffelStudio documentation is available in a convenient Wiki format. This makes it possible to improve the documentation continuously and make sure it is always up to date.
Community input is welcome.
==Using the Comments pages==
Each documentation page has an associated '''Comments''' page. Any viewer can add comments to a Comments page. These comments are periodically reviewed and appropriate content is "published," that is, made visible to the community.
===Guidelines for Comments pages===
#The '''Comments''' pages are intended to be used to record and communicate issues concerning the documentation. Use Comments pages to post comments which report problems with the documentation or which suggest improvements to the documentation.
# '''Any material you add to this site becomes the property of Eiffel Software, and may be shared with the community.'''
# Comments pages should ''not'' be used for product support questions, product feature requests, or bug reports. ''Comments of this sort will be deleted.'' For help with products join the [http://groups.eiffel.com Eiffel Software User Group] and use the resources at the [http://community.eiffel.com Eiffel Community site].
===Comment lifecycle===
Although the procedure for how editors deal with comments is flexible, some general guidelines can be given:
# For comments requesting action (e. g., fix a problem, add more information):
## For those actions which can be accomplished immediately:
### The comment will not be published.
### The requested action will be fixed.
### The original comment's subject line will be prepended with "FIXED".
## For those actions which cannot be accomplished quickly or require special handling:
### The comment will be published
### A response to the comment will be made via "reply", and
#### The original comment's subject line will be prepended with:
##### FIXED, if and when the request can be satisfied.
##### ANALYZED, otherwise, plus explanation of delaying or not acting on request.
## For actions affecting docs.eiffel.com plus the Eiffel distribution:
### Submit a problem report requesting feedback when problem is fixed so that docs.eiffel.com can be updated in kind.
# For comments not requesting action, but adding relevant information related to the page:
## The comment will be published.
## If appropriate:
### The content of the comment will be integrated into the page.
### The original comment's subject line prepended with FIXED.
# Periodically, an audit will remove older comments marked as FIXED and ANALYZED.
==Contributors and Editors==
If you are interested in a more active role in improving and developing EiffelStudio documentation, you can become:
* A contributor: authorized to edit existing pages to any book, and to add pages to the "Community" book.
**"Community" book pages can be added to other books by an editor.
* An editor: authorized to modify and add pages in any book.
To become a contributor, you should be proficient in Eiffel technology and have good written English skills. To become an editor, you should already be a contributor and have contributed significant improvements or additions to the documentation.
If you are interested in becoming a contributor, you can [[path:user/register|register]] for an account, and then please [[path:contact|contact us]] with a short description of your Eiffel experience and any other relevant background.
===Guidelines for contributors===
# '''Entering log messages:''' When you change pages in the documentation, it can help sometimes if you can provide an explanation of your intent in the '''Log message''' box on the '''Edit''' page. This can eliminate confusion about why things have been changed. Of course, it is not necessary to provide a log message for every change. For fixing typographical errors or other simple changes, it generally would not be necessary, but putting a single lowercase '''"m"''' in the '''Log message''' field will convey the message that this was a minor update. If you are evolving new pages or a complex set of related changes to one or more pages, it should suffice to enter a single log message at the beginning of the series of edits. Use common sense here.
#* In cases in which a change is directly related to an external document or policy, it may be helpful to mention the impetus in the log message. For example, documentation changes made to satisfy Eiffel Software problem reports should reference the report in the log message.
# '''Renaming pages or moving pages to Trash:''' Before you rename a page or move it to the Trash, you should use the '''References''' tab to make certain that there are no current references to the page. If there are, make sure you resolve those references before renaming or moving the page.
# '''Replacing pages:''' If you need to replace a page completely, do so by replacing the '''content''' of the existing page, rather than moving the page to the Trash and creating a new page in its place. Replacing the content will leave the original page (and its UUID) in place, but with the new content. UUID's are used by the [[Eiffel Information System]] (EIS) to link EiffelStudio to documentation pages, and will be broken if the original page were to be deleted.
# '''Using templates:'''
## There are several "templates" available for use within the text of documentation pages. For example, "Note", "SeeAlso", "Rule", "Definition", "Caution". You can click on "List templates" in the left margin to see the list of available templates.
## While developing new pages or make significant changes to existing pages you may want to mark the tops of these pages temporarily with certain templates during the development process. The "top-of-the-page" templates most useful during page maintenance are Beta, ReviewRequested, UnderConstruction, and UpdateNeeded. The meanings of these are described below.
==="Top-of-the-page" Documentation template meanings===
====Beta====
Looks like this:
{{Beta}}
Means this:
:''Use this page with caution. This page is currently under development as a new page or a replacement for a previously existing page. It may contain information which describes capabilities not yet implemented. Avoid linking to this page. When this page comes out of beta, it is likely that the name and/or UUID of this page will change.''
====ReviewRequested====
Looks like this:
{{ReviewRequested}}
Means this:
:''The material on this page needs to be reviewed for completeness and accuracy. If you have knowledge of this material, please review this page. If you are a [[Community|contributor]], feel free to make any appropriate additions and/or corrections, then remove this template. If not, you can note improvements on the [[Community#Using the Comments pages|comments]] page.''
====UnderConstruction====
Looks like this:
{{UnderConstruction}}
Means this:
:''Use this page with caution. This page is currently under development. It is likely that the information on this page is still incomplete. ''
====UpdateNeeded====
Looks like this:
{{UpdateNeeded}}
Means this:
:''Use this page with caution. This page has been identified as needing update. If you are a [[Community|contributor]], you can help by updating this page so that the information on it is current.''

View File

@@ -0,0 +1,5 @@
[[Property:title|Draft]]
[[Property:weight|99]]
[[Property:uuid|c277e707-67a0-14a2-099e-5b861f2480ad]]

View File

@@ -0,0 +1,49 @@
[[Property:title|Multiple inheritance]]
[[Property:weight|0]]
[[Property:uuid|7f54afce-fd1d-fba7-7a55-f74604ea9846]]
<h2>Multiple inheritance: definition</h2>
Multiple inheritance is a mechanism for combining abstractions. It lets you define a class by extending or specializing two or more classes, not just one as in <em>single</em> inheritance. For example you might define a multi_function printer as the combination of a printer and a scanner.
Multiple inheritance sometimes has the reputation of being complicated or even messy, but there is no such problem in Eiffel. "Name clashes", for example, are not a big deal: if classes <eiffel>A</eiffel> and <e>B</e> both have a feature with the same name <e>f</e> and class <e>C</e> inherits from both, you can either specify that they should be merged, or keep them separate through the <e>rename</e> mechanism. Details below.
<h2>Multiple inheritance basics</h2>
Multiple inheritance happens as soon as you list more than one class in the <e>inherit</e> clause at the beginning of a class. For example:
<eiffel>
class PRINTER feature
... Here the features specific to printers ...
end
class SCANNER feature
... Here the features specific to scanners ...
end
class MULTI_FUNCTION_PRINTER inherit
PRINTER
SCANNER
feature
... Here the features specific to printer-scanners ...
end
</eiffel>
As with single inheritance, the new class has access to the parent features, except that here they are features of two different parents. For example if <e>PRINTER</e> has feature <print> and <e>SCANNER</e> has features <e>scan</e> and <e>scanned</e>, then the feature clause of <e>SCANNER</e> can include
<code>
scan_and_print
-- Scan a page and print it.
do
scan -- Leaves result of scan in `scanned'
print (scanned)
end
</code>

View File

@@ -0,0 +1,5 @@
[[Property:title|Test page]]
[[Property:weight|0]]
[[Property:uuid|6dc09e0f-b713-8c5b-799f-36a60264e8f8]]
Test page for Book "Draft"

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View File

@@ -0,0 +1,3 @@
title=static documentation page
author=halw
path=content/static-documentation-page

View File

@@ -0,0 +1,186 @@
[[Property:title|Guide]]
[[Property:description|Central repository of information about Eiffel and the products and technologies of Eiffel Software]]
[[Property:link_title|Information Guide]]
[[Property:weight|10]]
[[Property:uuid|68b37685-64e9-f564-9258-29e709a55f44]]
'''Guide to Eiffel Information'''
These pages are the central repository of information about Eiffel and the products and technologies of Eiffel Software. They cover the online documentation, but also link to many valuable resources outside the documentation set.
If you are interested in [[Learning Eiffel|learning Eiffel, there is a list of resources]] dedicated to that purpose.
The online documentation is organized into virtual books. Each book covers an important aspect of the world of Eiffel. For cases in which it is not always possible to use the online version of the documentation, all or selected parts of the documentation set can be [[Offline use of the Eiffel documentation|downloaded for offline use]].
* [[Guide]] -- Guide to Eiffel Information
* [[EiffelStudio]] -- The EiffelStudio Interactive Development Environment
* [[Solutions]] -- Eiffel Solutions, Technologies, and Class Libraries
* [[Platform specifics]] -- Specific support for particular platforms, e.g., Microsoft Windows
* [[Method|Method and Language]] -- The Eiffel Method and Language
* [[Why Eiffel?]] -- Why Eiffel?
* [[Papers]] -- Technical and position papers relating to Eiffel and the engineering of high quality software
* [[Examples]] -- Contributor supported examples of Eiffel solutions to common programming problems
* [[Community]] -- Community Contributions
<!--break-->
Sources of information on Eiffel include:
==Books in the Eiffel Documentation==
----
===[[Guide]] -- Guide to Eiffel Information===
:You are reading this book now.
===[[EiffelStudio]] -- The EiffelStudio Interactive Development Environment===
:Information about installing and using EiffelStudio
===[[Solutions]] -- Eiffel Solutions, Technologies, and Class Libraries===
:Technologies available with Eiffel provide solutions to many ordinary development needs ... and some extraordinary needs too. This book addresses these requirements and the Eiffel technologies that satisfy them.
===[[Platform specifics]] -- Support for particular operating systems===
:Although most Eiffel technology is completely platform-independent, Eiffel also provides important platform-specific solutions, described in this book.
===[[Method|Method and Language]] -- The Eiffel Method and Language===
:Materials promoting the understanding of the Eiffel software development method and the Eiffel programming language.
===[[Why Eiffel?]] -- Why Eiffel? ===
:A summary of the arguments for using Eiffel.
===[[Papers]] -- Technical and position papers relating to Eiffel===
:This book is a place for white papers which provide background, foundation, or supplemental information about the the Eiffel method and language as well as the goal of engineering high quality software.
===[[Examples]] -- Contributor supported examples of Eiffel solutions to common programming problems===
:Let's build a set of examples that can be shared on popular WWW program chrestomathies.
===[[Community]] -- You can contribute to the documentation!===
:EiffelStudio documentation is available in a convenient Wiki format. This makes it possible to improve the documentation continuously and make sure it is always up to date.
'''Community input''' is welcome. If you are interested in improving and developing EiffelStudio documentation, you can become a ''contributor'' or ''editor'':
* Contributors can edit existing pages in any book and add pages to Community Contributions books.
* Editors can modify and add pages in any book (including adding Community Contribution pages to an existing book).
To become a contributor, you should be proficient in Eiffel technology and have good written English skills. To become an editor, you should already have made significant improvements or additions as a contributor.
If you are interested in becoming a contributor, please send an email to info@eiffel.com with a short description of your Eiffel experience and any other relevant background. We look forward to your contributions!
----
==Other sources of information on Eiffel==
----
===The [http://eiffel.com Eiffel.com] website===
Eiffel Software's website [http://eiffel.com Eiffel.com] contains an enormous amount of information about Eiffel. There are product descriptions, special pages for developers and their managers, case studies and testimonials, the latest Eiffel news, and much more.
----
===[http://eiffel.com/developers/presentations/ Web Presentations] on Eiffel.com===
Learn quickly about Eiffel and the things that help make it special, like Design by Contract and EiffelStudio. Learn how Eiffel fits in with and compares to other popular technologies. All this and more is available on the [http://eiffel.com/developers/presentations/ presentations page] on Eiffel.com.
----
===[http://eiffel.com/developers/learning_maps/ Learning Maps] on Eiffel.com===
Get an in-depth view of topics by navigating the [http://eiffel.com/developers/learning_maps/ Eiffel Learning Maps]. Learning maps represent knowledge as a network of interrelated concepts. Attached to the concepts you may find links to additional resources. These resources can be just about anything. You'll find plain text files, web pages, screen shots, and even Eiffel Learnlets. Learnlets are small units of learning in web presentation form that are designed to take no more than 30 minutes to view ... just right for your lunch break.
----
===The [http://www.eiffelroom.com/ EiffelRoom] Website===
[http://www.eiffelroom.com/ EiffelRoom] is an Eiffel community website on which Eiffel developers from across the globe come together and share their experiences ... and their products. You'll find how-to articles, tips and tricks, example code, whole libraries of EIffel classes, and specialized products. It is easy to contribute to EiffelRoom and start giving back to the community.
----
===The Eiffel Software User Group===
The Eiffel Software Users' Group is a focus group for those who use the products of Eiffel Software. Its primary communication vehicle is a [http://groups.eiffel.com/ collaborative discussion group]. The group mailing list is monitored by Eiffel Software developers and many highly experienced Eiffel programmers. So if you have questions or comments about Eiffel Software products, this is a good place to be.
----
===The EiffelWorld Newsletter===
A few times a year, we send out an email newsletter containing announcements of new versions of products, upcoming events, newly added technologies, website changes, editorials, and contributions from the community. To subscribe send a request to [mailto:info@eiffel.com info@eiffel.com].
----
===[[Object-Oriented Software Construction, 2nd Edition]]===
There is no better place to gain an in-depth understanding of the Eiffel software development method than [[Object-Oriented Software Construction, 2nd Edition]], by Bertrand Meyer, published by Prentice Hall. It is the world's most complete guide to building great object-oriented software.
----
===Other [[Books about the Eiffel Method and Language|books about the Eiffel Method and Language]]===
----
===The Standard: ''Eiffel: Analysis, Design, and Programming Language''===
Eiffel has been standardized under ISO and ECMA. The comprehensive description of the standard Eiffel programming language is presented in [http://www.ecma-international.org/publications/standards/Ecma-367.htm Standard ECMA-367].
----
===Contribute to Eiffel===
You can help Eiffel by contributing your time, expertise, and products. Here are some websites that you can visit to see what's up with the development of Eiffel Software products.
====[http://dev.eiffel.com dev.eiffel.com]====
:This [http://dev.eiffel.com wiki site] is the hub of development activity for the EiffelStudio interactive development environment. Even if you do not plan to contribute, dev.eiffel.com is a valuable source of information concerning where EiffelStudio is going ... and, if you're curious, where it has been.
====[http://eiffelstudio.origo.ethz.ch/ EiffelStudio on Origo]====
:[http://eiffelstudio.origo.ethz.ch/ EiffelStudio on Origo] contains blogs and forums focusing on Eiffel and EiffelStudio topics.
----
==[[uuid:b8c10baa-4f50-adfe-a6f8-9cb56a8f1917|Glossary of Object Technology]]==
----
This is a relatively comprehensive glossary of terms used in Object-Oriented Analysis, Design, and programming, but are not specific to the Eiffel Language, since object-oriented principles can be applied to any programming language. It contains all the terms from the glossary in [[Object-Oriented Software Construction, 2nd Edition]], plus others used in this website, added for clarity and ease of reference.
This glossary is useful all by itself, since a review of it can serve as a refresher (in case you have been away from Object Technology for a while). It is used in this website to assist the reader by providing easy links to technical terms that are used throughout the website.
Additionally, it is possible to link to terms in this glossary from other websites by using links that look like this:
:<nowiki>http://docs.eiffel.com/book/guide/glossary-object-technology#Attribute</nowiki>
or a version that will survive the page being moved:
:<nowiki>http://docs.eiffel.com/isedoc/uuid/b8c10baa-4f50-adfe-a6f8-9cb56a8f1917#Attribute</nowiki>
Note that the anchor (the part after the "#") has to be spelled and capitalized exactly like the term on the page. (Use underscore characters to replace spaces.)
----

View File

@@ -0,0 +1,30 @@
[[Property:title|Offline use of the Eiffel Documentation]]
[[Property:link_title|Download Documentation]]
[[Property:weight|0]]
[[Property:uuid|e5f003f6-c732-c648-fd67-91f6642130f0]]
It is possible to download the books of the Eiffel online documentation for viewing offline with a web browser.
To do this you use a [http://docs.eiffel.com/static/ web page] which has links to downloadable files that contain copies of the documentation in different forms and quantities.
[[Image:static documentation page|Downloadable documentation]]
The files are ".7z" files, meaning that they are compressed archives in [http://www.7-zip.org 7-zip] format. So, you can use any 7-zip compatible expander to unpack the files.
You'll notice that the options for downloading come in three groups:
# HTML: Multiple pages per book.
# HTML: One big page per book.
# WikiText+meta: raw files containing wikitext (backup)
You should choose your files from one of the HTML options (the WikiText option is used for backup).
It is possible also to download one documentation "book" at a time, or to download all books in one archive.
The files are static copies of the content of the online documentation, as reflected by the dates shown on the web page.

View File

@@ -0,0 +1,11 @@
[[Property:title|Why Eiffel?]]
[[Property:description|arguments for using Eiffel]]
[[Property:weight|11]]
[[Property:uuid|df007537-c0dd-2ea6-233b-764ad483eb65]]
This book collects arguments for using Eiffel.
Even though we in the Eiffel community know that Eiffel is the most advanced object-oriented software development framework on this planet, that fact may not be so obvious to everyone else. Consequently, we felt that it would be helpful to provide some brief documents that spell out the reasons why the people who have chosen Eiffel have been so successful.
You may find the information helpful if you are simply curious about Eiffel, if you are actively looking for a better development framework, or if you are busy trying to convince others to try Eiffel.

View File

@@ -0,0 +1 @@
<p class="tpl header-message">[[Image:LogoBeta|24px]] '''Beta documentation:''' [[How to contribute to documentation#Beta|see definition]].</p>

View File

@@ -0,0 +1,3 @@
title=Beta
author=vwheeler
path=content/beta

View File

@@ -0,0 +1,2 @@
<p style="margin-left: 10px; margin-right: 50px; border: 1px solid #FFB55F; padding: 10px; background-color: #FFEEBF; color: black;">[[Image:LogoWarning|24px]] '''Caution:''' {{{1}}}</p>

View File

@@ -0,0 +1,3 @@
title=Caution
author=admin
path=content/caution-0

View File

@@ -0,0 +1 @@
<p class="tpl info-message">[[Image:LogoInformation|24px]] '''Info: '''{{{1}}}</p>

View File

@@ -0,0 +1,3 @@
title=Info
author=admin
path=content/info

View File

@@ -0,0 +1 @@
<span class="tpl error-message">{{{1}}}</span>

View File

@@ -0,0 +1 @@
<span class="tpl info-message">{{{1}}}</span>

View File

@@ -0,0 +1 @@
<span class="tpl success-message">{{{1}}}</span>

View File

@@ -0,0 +1 @@
<span class="tpl warning-message">{{{1}}}</span>

View File

@@ -0,0 +1 @@
<span class="tpl key-message">{{{1}}}</span>

View File

@@ -0,0 +1,3 @@
title=Key
author=admin
path=content/key

View File

@@ -0,0 +1 @@
<p class="tpl note-message">[[Image:LogoInformation|24px]] '''Note: '''{{{1}}}</p>

View File

@@ -0,0 +1,3 @@
title=Note
author=admin
path=content/note

View File

@@ -0,0 +1 @@
<p class="tpl recommended-message">[[Image:LogoRecommended|24px]] '''Recommended: '''{{{1}}}</p>

View File

@@ -0,0 +1,3 @@
title=Recommended
author=admin
path=content/recommended

View File

@@ -0,0 +1 @@
<p class="tpl header-message" style="background-color: #FFFFFF; border-color: black">[[Image:LogoReviewRequested|24px]] '''Review requested: ''' [[How to contribute to documentation#ReviewRequested|see definition]].</p>

View File

@@ -0,0 +1,3 @@
title=ReviewRequested
author=vwheeler
path=content/reviewrequested

View File

@@ -0,0 +1 @@
<p class="tpl rule-message">[[Image:LogoRule|24px]] '''Rule -- {{{name}}}:''' {{{text}}}</p>

View File

@@ -0,0 +1,3 @@
title=Rule
author=halw
path=content/rule

View File

@@ -0,0 +1 @@
<p class="tpl sample-message">[[Image:LogoInformation|24px]] '''Sample:''' {{{1}}}</p>

View File

@@ -0,0 +1,3 @@
title=Sample
author=admin
path=content/sample

View File

@@ -0,0 +1 @@
<p class="tpl seealso-message">[[Image:LogoInformation|24px]] '''See Also:''' {{{1}}}</p>

View File

@@ -0,0 +1,3 @@
title=SeeAlso
author=admin
path=content/seealso

View File

@@ -0,0 +1 @@
<p class="tpl tip-message">[[Image:LogoInformation|24px]] '''Tip: '''{{{1}}}</p>

View File

@@ -0,0 +1,3 @@
title=Tip
author=admin
path=content/tip

View File

@@ -0,0 +1 @@
<p class="tpl header-message">[[Image:LogoConstruction|24px]] '''Under construction:''' [[How to contribute to documentation#UnderConstruction|see definition]].</p>

View File

@@ -0,0 +1,3 @@
title=UnderConstruction
author=vwheeler
path=content/underconstruction

View File

@@ -0,0 +1 @@
<p class="tpl header-message">[[Image:LogoUpdateNeeded|24px]] '''Update Needed:''' [[How to contribute to documentation#UpdateNeeded|see definition]].</p>

View File

@@ -0,0 +1,3 @@
title=UpdateNeeded
author=vwheeler
path=content/updateneeded

View File

@@ -0,0 +1 @@
<p class="tpl warning-message">[[Image:LogoWarning|24px]] '''Warning:''' {{{1}}}</p>

View File

@@ -0,0 +1,3 @@
title=Warning
author=admin
path=content/warning

View File

@@ -0,0 +1 @@
<p class="tpl definition-message">[[Image:LogoDefinition|24px]] '''Definition -- {{{1}}}''': {{{2}}}</p>

View File

@@ -0,0 +1,3 @@
title=definition
author=halw
path=content/definition

View File

@@ -0,0 +1,44 @@
[[Property:title|How to contribute to documentation]]
[[Property:link_title|To documentation]]
[[Property:weight|2]]
[[Property:uuid|A2DED192-B50A-4E59-B214-FDC3FEDC7A44]]
= Current documentation system =
* The documentation is written using wikitext syntax (similar to wikipedia).
* Each documentation page is stored in a wiki file on disk.
* Those files come from the subversion repository: [https://svn.eiffel.com/eiffel-org/trunk/documentation/trunk] .
* The outline of book are following the underlying directory structure, and each wiki file can have properties that hold metadata such as:
<code>
[[Property:title|The page title]]
[[Property:link_title|short title]]
[[Property:weight|5]]
</code>
** '''link_title''' is used to have a short title in menu, or various links.
** '''weight''' is used to order sibling pages (lower weight goes before, upper weight goes after).
= To contribute =
* First, you can post comment on any page (see comment form at the bottom of each page).
* As one would contribute to any source maintained on a subversion repository, one can contribute via the repository [https://svn.eiffel.com/eiffel-org/trunk/documentation/trunk/] and provide patch.
* Note there is also a git mirror at [https://github.com/eiffelsoftware/eiffel-org] so you can also contribute via github by sending pull request.
= Step by step with git =
* Go to [https://github.com/eiffelsoftware/eiffel-org] for the project, then git clone on your machine.
* create a git branch.
* add or edit the files locally.
* once you want to share your changes.
** git commit your changes.
** git push them to your github repository.
** then create a pull request so that the Eiffel.org documentation team can review and integrate the changes.
* See current pull requests at [https://github.com/EiffelSoftware/eiffel-org/pulls].
= Step by step with subversion =
* <code>svn checkout https://svn.eiffel.com/eiffel-org/trunk/documentation/trunk/</code>.
* add or edit the files locally.
* once you want to share your changes.
** svn update.
** Send the patch via [https://codereview.appspot.com/]. (note: follow the instructions from codereview site, you will need to use a python script "upload.py" distributed by the codereview site).
* See current patches at [https://codereview.appspot.com/search?base=https://svn.eiffel.com/eiffel-org/trunk/documentation/trunk/].
= Live editing on this site =
* If you are a trusted editor, you can edit the documentation directly.
* To be a trusted editor, please request it via the [https://www.eiffel.org/contact contact] page (do not forget to mention who you are and why you think you should be a trusted editor).

View File

@@ -0,0 +1,123 @@
[[Property:title|Help to edit documentation]]
[[Property:link_title|Editing help]]
[[Property:weight|3]]
= Wikitext syntax =
* Have a look at [https://en.wikipedia.org/wiki/Help:Wiki_markup Wikipedia markup] documentation.
* The current website does not support the full Wikipedia syntax, but still most of the needed cases.
* To embed inline code:
** `` `foo.bar` ``
** `<code>foo.bar</code>`
** `<eiffel>foo.bar</eiffel>`
* To embed block code:
```xml
<code lang="eiffel">
class FOOBAR
</code>
```
```xml
<eiffel>
class FOOBAR
</eiffel>
```
<code lang="text">
```eiffel
class FOOBAR
```
</code>
Note: if you do not specify the lang, it is defaulted to "eiffel"
= Templates =
== Top page templates ==
Used to qualify the current page.
=== ReviewRequested ===
:<nowiki>{{ReviewRequested|This is a ReviewRequested message}}</nowiki>
{{ReviewRequested|This is a ReviewRequested message}}
=== UnderConstruction ===
:<nowiki>{{UnderConstruction|This is a UnderConstruction message}}</nowiki>
{{UnderConstruction|This is a UnderConstruction message}}
=== UpdateNeeded ===
:<nowiki>{{UpdateNeeded|This is a UpdateNeeded message}}</nowiki>
{{UpdateNeeded|This is a UpdateNeeded message}}
=== Beta ===
:<nowiki>{{Beta|This is a beta message}}</nowiki>
{{Beta|This is a beta message}}
== Block templates ==
=== Caution ===
:<nowiki>{{Caution|This is a caution message}}</nowiki>
{{Caution|This is a caution message}}
=== Definition ===
:<nowiki>{{Definition|abc|This is a Definition message}}</nowiki>
{{Definition|abc|This is a Definition message}}
=== Info ===
:<nowiki>{{Info|This is a Info message}}</nowiki>
{{Info|This is a Info message}}
=== Note ===
:<nowiki>{{Note|This is a Note message}}</nowiki>
{{Note|This is a Note message}}
=== Recommended ===
:<nowiki>{{Recommended|This is a Recommended message}}</nowiki>
{{Recommended|This is a Recommended message}}
=== Rule ===
:<nowiki>{{Rule|name=abc|text=This is a Rule message}}</nowiki>
{{Rule|name=abc|text=This is a Rule message}}
=== Sample ===
:<nowiki>{{Sample|This is a Sample message}}</nowiki>
{{Sample|This is a Sample message}}
=== SeeAlso ===
:<nowiki>{{SeeAlso|This is a SeeAlso message}}</nowiki>
{{SeeAlso|This is a SeeAlso message}}
=== Tip ===
:<nowiki>{{Tip|This is a Tip message}}</nowiki>
{{Tip|This is a Tip message}}
=== Warning ===
:<nowiki>{{Warning|This is a Warning message}}</nowiki>
{{Warning|This is a Warning message}}
== Inline templates ==
=== Key ===
:<nowiki>This is a {{Key|key message}} in the text. </nowiki>
This is a {{Key|key message}} in the text.
=== Error ===
:<nowiki>This is a {{Inline-Error|error message}} in the text. </nowiki>
This is a {{Inline-Error|error message}} in the text.
=== Info ===
:<nowiki>This is a {{Inline-Info|info message}} in the text. </nowiki>
This is a {{Inline-Info|info message}} in the text.
=== Success ===
:<nowiki>This is a {{Inline-Success|success message}} in the text. </nowiki>
This is a {{Inline-Success|success message}} in the text.
=== Warning ===
:<nowiki>This is a {{Inline-Warning|warning message}} in the text. </nowiki>
This is a {{Inline-Warning|warning message}} in the text.

View File

@@ -0,0 +1,10 @@
[[Property:title|How to contribute 123456]]
[[Property:description|How to contribute]]
[[Property:link_title|Contribute]]
[[Property:weight|6]]
[[Property:uuid|56480505-4CD5-4C8A-AA3D-120FD573DFA9]]
= How to contribute to Eiffel ? =
Check page [https://www.eiffel.org/contribute] .

View File

@@ -0,0 +1,63 @@
[[Property:title|Example: Command line arguments]]
[[Property:weight|0]]
[[Property:uuid|ba852d83-3c02-4d38-088a-60b76fe5c63f]]
==Description==
Retrieve the list of command-line arguments given to the program.
Example command line:
<code lang="text">
myprogram -c "alpha beta" -h "gamma"
</code>
==Notes==
This class inherits functionality for dealing with command line arguments from class <code lang="eiffel">ARGUMENTS</code>. It uses the feature <code lang="eiffel">separate_character_option_value</code> to return the values by option name for each of the two arguments. <code lang="eiffel">ARGUMENTS</code> provides a rich set of features for command line argument processing.
The simple version in [[#Solution|Solution]] below is as submitted to Rosetta Code to illustrate class <code lang="eiffel">ARGUMENTS</code>, but it should be noted that <code lang="eiffel">separate_character_option_value</code> is of a detached type and will return a void reference if no value is found for a specified character option. Therefore, a safer version of the use of <code lang="eiffel">separate_character_option_value</code> would include object test on the result:
<code>
if attached separate_character_option_value ('c') as l_val then
print ("Command line argument value for option 'c' is: ")
print (l_val + "%N")
end
if attached separate_character_option_value ('h') as l_val then
print ("Command line argument value for option 'h' is: ")
print (l_val + "%N")
end
</code>
==Source==
Problem description from [http://rosettacode.org/wiki/Command-line_arguments Rosetta Code]
==Solution==
<code>
class
APPLICATION
inherit
ARGUMENTS
create
make
feature {NONE} -- Initialization
make
-- Print values for arguments with options 'c' and 'h'.
do
print ("Command line argument value for option 'c' is: ")
print (separate_character_option_value ('c') + "%N")
print ("Command line argument value for option 'h' is: ")
print (separate_character_option_value ('h') + "%N")
io.read_line -- Keep console window open
end
end
</code>
==Output (for command line arguments: -c "alpha beta" -h "gamma")==
<code lang="text">
Command line argument value for option 'c' is: alpha beta
Command line argument value for option 'h' is: gamma
</code>

View File

@@ -0,0 +1,41 @@
[[Property:title|Example: Environment variables]]
[[Property:weight|0]]
[[Property:uuid|60c39a34-0794-4c1f-a150-7431afa3e693]]
==Description==
Using features from the class <code>EXECUTION_ENVIRONMENT</code> to create and retrieve an environment variable.
==Notes==
The <code>make</code> procedure of the class <code>APPLICATION</code> below uses the features <code>put</code> and <code>get</code>, inherited from the class <code>EXECUTION_ENVIRONMENT</code>, to create the environment variable <code>MY_VARIABLE</code> with value "Hello World!", and then to retrieve the value by key and print it.
==Solution==
<code>
class
APPLICATION
inherit
EXECUTION_ENVIRONMENT
create
make
feature {NONE} -- Initialization
make
-- Create and retrieve an environment variable.
do
put ("Hello World!", "MY_VARIABLE")
print (get ("MY_VARIABLE"))
end
end
</code>
==Output==
<code lang="text">
Hello World!
</code>

View File

@@ -0,0 +1,52 @@
[[Property:title|Example: File IO]]
[[Property:weight|0]]
[[Property:uuid|b26aa8e3-5963-94ae-b523-642c8b79637b]]
==Description==
Create a file "output.txt" containing the contents of "input.txt".
==Source==
Problem description from [http://rosettacode.org/wiki/File_IO Rosetta Code: File IO]
==Solution==
<code>
class
APPLICATION
create
make
feature {NONE} -- Initialization
make
-- Run application.
do
create input_file.make_open_read ("input.txt")
create output_file.make_open_write ("output.txt")
from
input_file.read_character
until
input_file.exhausted
loop
output_file.put (input_file.last_character)
input_file.read_character
end
input_file.close
output_file.close
end
feature -- Access
input_file: PLAIN_TEXT_FILE
output_file: PLAIN_TEXT_FILE
end
</code>

View File

@@ -0,0 +1,218 @@
[[Property:title|Example: Polymorphism]]
[[Property:weight|0]]
[[Property:uuid|e4a9db32-c087-21b7-f0d6-4685f0ce249d]]
==Description==
Create a class POINT and its heir CIRCLE to demonstrate polymorphic attachment and dynamic binding.
==Source==
Problem description from [http://rosettacode.org/wiki/Polymorphism Rosetta Code: Polymorphism]
Solution varies from Rosetta Code description (e. g., feature <code>out</code> is redefined in this solution, versus feature <code>print</code>.)
==Solution==
<code>
class
POINT
inherit
ANY
redefine
out
end
create
make, make_origin
feature -- Initialization
make (a_x, a_y: INTEGER)
-- Create with values `a_x' and `a_y'
do
set_x (a_x)
set_y (a_y)
ensure
x_set: x = a_x
y_set: y = a_y
end
make_origin
-- Create at origin
do
ensure
x_set: x = 0
y_set: y = 0
end
feature -- Access
x: INTEGER assign set_x
-- Horizontal axis coordinate
y: INTEGER assign set_y
-- Vertical axis coordinate
feature -- Element change
set_x (a_x: INTEGER)
-- Set `x' coordinate to `a_x'
do
x := a_x
ensure
x_set: x = a_x
end
set_y (a_y: INTEGER)
-- Set `y' coordinate to `a_y'
do
y := a_y
ensure
y_set: y = a_y
end
feature -- Output
out: STRING
-- Display as string
do
Result := "Point: x = " + x.out + " y = " + y.out
end
end
</code>
<code>
class
CIRCLE
inherit
POINT
rename
make as point_make
redefine
make_origin,
out
end
create
make, make_origin, make_from_point
feature -- Initialization
make (a_x, a_y, a_r: INTEGER)
-- Create with values `a_x' and `a_y' and `a_r'
require
non_negative_radius_argument: a_r >= 0
do
point_make (a_x, a_y)
set_r (a_r)
ensure
x_set: x = a_x
y_set: y = a_y
r_set: r = a_r
end
make_origin
-- Create at origin with zero radius
do
Precursor
ensure then
r_set: r = 0
end
make_from_point (a_p: POINT; a_r: INTEGER)
-- Initialize from `a_r' with radius `a_r'.
require
non_negative_radius_argument: a_r >= 0
do
set_x (a_p.x)
set_y (a_p.y)
set_r (a_r)
ensure
x_set: x = a_p.x
y_set: y = a_p.y
r_set: r = a_r
end
feature -- Access
r: INTEGER assign set_r
-- Radius
feature -- Element change
set_r (a_r: INTEGER)
-- Set radius (`r') to `a_r'
require
non_negative_radius_argument: a_r >= 0
do
r := a_r
ensure
r_set: r = a_r
end
feature -- Output
out: STRING
-- Display as string
do
Result := "Circle: x = " + x.out + " y = " + y.out + " r = " + r.out
end
invariant
non_negative_radius: r >= 0
end
</code>
<code>
class
APPLICATION
create
make
feature {NONE} -- Initialization
make
-- Run application.
local
my_point: POINT
my_circle: CIRCLE
do
create my_point.make_origin
print (my_point.out + "%N")
create {CIRCLE} my_point.make_origin
print (my_point.out + "%N")
create my_point.make (10, 15)
print (my_point.out + "%N")
create {CIRCLE} my_point.make (20, 25, 5)
print (my_point.out + "%N")
create my_circle.make (30, 35, 10)
print (my_circle.out + "%N")
create my_circle.make_from_point (my_point, 35)
print (my_circle.out + "%N")
end
end
</code>
==Output==
<code lang="text">
Point: x = 0 y = 0
Circle: x = 0 y = 0 r = 0
Point: x = 10 y = 15
Circle: x = 20 y = 25 r = 5
Circle: x = 30 y = 35 r = 10
Circle: x = 20 y = 25 r = 35
</code>

View File

@@ -0,0 +1,41 @@
[[Property:title|Example: Reverse a string]]
[[Property:weight|0]]
[[Property:uuid|d888d308-6bb7-edd5-ee25-92d04b5658d3]]
==Description==
Reverse the order of the characters in a give string of characters.
==Source==
Problem description from [http://rosettacode.org/wiki/Reverse_a_string Rosetta Code]
==Solution==
<code>
class
APPLICATION
create
make
feature
make
-- Demonstrate string reversal.
do
my_string := "Hello World!"
my_string.mirror
print (my_string)
end
my_string: STRING
-- Used for reversal
end
</code>
==Output==
<code lang="text">
!dlroW olleH
</code>

View File

@@ -0,0 +1,84 @@
[[Property:title|Example: Self-initializing attributes and assigner commands]]
[[Property:weight|0]]
[[Property:uuid|dbc107a4-42cd-606a-71b2-e0b70ac5482e]]
==Description==
Example of using a [[Void-safety: Background, definition, and tools#Self-initializing attributes|self-initializing attribute]] and an [[ET: The Dynamic Structure: Execution Model#Assigner commands|assigner command]].
==Notes==
The concepts of [[Void-safety: Background, definition, and tools#Self-initializing attributes|self-initializing attributes]] and [[ET: The Dynamic Structure: Execution Model#Assigner commands|assigner commands]] are independent of one another. However, this example shows how each works in a small amount of code.
The example consists of two classes: a root class, and class <code>PERSON</code>. The <code>PERSON</code> class has a self-initializing attribute of type <code>STRING</code> named <code>mood</code>. If <code>mood</code> is accessed before it is explicitly initialized, then the self-initializing code after the keyword <code>attribute</code> will be executed, setting the default mood to "Happy".
The attribute <code>mood</code> also has an assigner command, the procedure <code>set_mood</code>, designated as such by the <code>assign</code> keyword. This allows clients of class <code>PERSON</code> to appear to assign directly to <code>mood</code>. However, the assigner command <code>set_mood</code> will always get executed, and its precondition will be in force during such an apparent assignment.
The root class <code>APPLICATION</code> creates an instance of <code>PERSON</code> and prints the value of <code>mood</code>, getting the self-iniitalized value. Then it assigns to <code>mood</code>. When it prints again, it gets the updated value.
==Source==
Adapted from an example given on the Eiffel Software Users Group.
==Solution==
A root class:
<code>
class
APPLICATION
create
make
feature {NONE} -- Initialization
make
-- Print and set mood of `my_person'.
do
create my_person
print ("Mood: " + my_person.mood + "%N")
my_person.mood := "Ecstatic"
print ("Mood: " + my_person.mood + "%N")
end
feature -- Access
my_person: PERSON
end
</code>
Class PERSON:
<code>
class
PERSON
feature -- Access
mood: STRING assign set_mood
attribute
Result := "Happy"
end
feature -- Element change
set_mood (a_string: STRING)
require
single_token: a_string.occurrences (' ') = 0
do
mood := a_string
ensure
mood_set: mood = a_string
end
end
</code>
==Output==
<code>
Mood: Happy
Mood: Ecstatic
</code>

View File

@@ -0,0 +1,64 @@
[[Property:title|Example: Sieve of Eratosthenes]]
[[Property:weight|0]]
[[Property:uuid|e825c874-4266-b5ee-501c-221e6940dacd]]
==Description==
Deliver prime numbers up to a specified integer limit. Compute prime numbers using sieve of Eratosthenes.
==Notes==
This example uses the ''iteration'' (<code>across</code>) form of the Eiffel loop construct to traverse a list, an array, and an integer interval.
==Source==
Problem description from [http://rosettacode.org/wiki/Sieve_of_Eratosthenes Rosetta Code]
==Solution==
<code>
class
APPLICATION
create
make
feature
make
-- Run application.
do
across primes_through (100) as ic loop print (ic.item.out + " ") end
end
primes_through (a_limit: INTEGER): LINKED_LIST [INTEGER]
-- Prime numbers through `a_limit'
require
valid_upper_limit: a_limit >= 2
local
l_tab: ARRAY [BOOLEAN]
do
create Result.make
create l_tab.make_filled (True, 2, a_limit)
across
l_tab as ic
loop
if ic.item then
Result.extend (ic.target_index)
across ((ic.target_index * ic.target_index) |..| l_tab.upper).new_cursor.with_step (ic.target_index) as id
loop
l_tab [id.item] := False
end
end
end
end
end
</code>
==Output==
<code lang="text">
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
</code>

View File

@@ -0,0 +1,54 @@
[[Property:title|Example: Sleep]]
[[Property:weight|0]]
[[Property:uuid|a846db1c-2096-43a9-bb8b-a233c9e21421]]
==Description==
Write a program that does the following in this order:
# Input an amount of time to sleep in whatever units are most natural for your language (milliseconds, seconds, ticks, etc.). This unit should be noted in comments or in a description.
# Print "Sleeping..."
# Sleep the main thread for the given amount of time.
# Print "Awake!"
# End.
==Notes==
The feature <code lang="eiffel">sleep</code> is defined in the library class <code>EXECUTION_ENVIRONMENT</code>. So the demonstration class <code>APPLICATION</code> inherits from <code>EXECUTION_ENVIRONMENT</code> in order to make <code lang="eiffel">sleep</code> available.
<code lang="eiffel">sleep</code> takes an argument which declares the number of nanoseconds to suspend the thread's execution.
==Source==
Problem description from [http://rosettacode.org/wiki/Sleep Rosetta Code]
==Solution==
<code>
class
APPLICATION
inherit
EXECUTION_ENVIRONMENT
create
make
feature -- Initialization
make
-- Sleep for a given number of nanoseconds.
do
print ("Enter a number of nanoseconds: ")
io.read_integer_64
print ("Sleeping...%N")
sleep (io.last_integer_64)
print ("Awake!%N")
end
end
</code>
==Output (sleeping 10 seconds)==
<code lang="text">
Enter a number of nanoseconds: 10000000000
Sleeping...
Awake!
</code>

View File

@@ -0,0 +1,10 @@
[[Property:title|Examples]]
[[Property:description|how common programming problems can be solved using Eiffel]]
[[Property:weight|6]]
[[Property:uuid|1a59e03b-8bf0-8426-43b4-577761e40790]]
Here you will find examples of how common programming problems can be solved using Eiffel.
A set of examples is also included with the EiffelStudio distribution kit.

View File

@@ -0,0 +1,24 @@
[[Property:title|Introduction to the Examples Book]]
[[Property:weight|-1]]
[[Property:uuid|044fa742-f3ca-9f5b-01cc-7194ee172b08]]
EiffelStudio comes with a rich set of examples that you can use to learn how to use the many Eiffel facilities and libraries. You should look first to the examples distributed with EiffelStudio as your primary source of samples of Eiffel in use.
The examples in this book are somewhat different in nature and serve a different purpose.
Although some of the examples included here are provided by Eiffel Software, the intent is that the majority of the entries will contributed by people like you who use Eiffel daily to solve real problems.
The inspiration for this book is the many ''program chrestomathies'' on the World-Wide Web. In natural language, a chrestomathy is a set of literary passages explicitly selected for the purpose of helping learn a language. A program chrestomathy is a set of problems for which solutions are represented in various programming languages with the aim of allowing programmers to compare language capabilities and programming techniques.
Program chrestomathies vary widely. At one end of the spectrum [http://99-bottles-of-beer.net/ 99 Bottles of Beer] has collected solutions in over one thousand programming languages, all targeted to a single problem: generate and print the complete lyrics of the song ''99 Bottles of Beer on the Wall''. There are several "Hello world!" chrestomathies. Other sites host multiple programming problems, all with solutions in many languages. One large multi-problem site is [http://rosettacode.org/wiki/Main_Page Rosetta Code]. In fact, Rosetta Code maintains a [http://rosettacode.org/wiki/Help:Similar_Sites list of links to many of the Web's other programming chrestomathy projects].
Eiffel has a presence on many of these sites. Still, the more examples, the better.
The purpose of the examples in this book, then, is two-fold. First, we get a set of Eiffel examples in the Eiffel online documentation with solutions to a different set of problems than the examples distributed with EiffelStudio. Second, examples from this set can be migrated to Rosetta Code or one of the other chrestomathies to improve Eiffel's presence on those sites. (The caveat to contributors is clear: '''Contribute only work that you have to authority to release, and only if you are willing to have your work shared on one or more of the program chrestomathies.''' By submitting content to this Examples book, you agree to release that content under terms no more restrictive than the GNU Free Documentation License.)
Sites like Rosetta Code and [http://en.literateprograms.org/LiteratePrograms:Welcome Literate Programs] offer a wide variety of programming problems or tasks for comparison of languages and techniques. Rosetta Code provides an index to the [http://rosettacode.org/wiki/Reports:Tasks_not_implemented_in_Eiffel tasks not yet implemented in Eiffel].
This book should include, but not necessarily be limited to, certain of the problems used as challenges by program chrestomathies.

View File

@@ -0,0 +1,6 @@
[[Property:title|Language reference]]
[[Property:link_title|Language]]
[[Property:weight|3]]
[[Property:uuid|17412f30-0451-4b2b-bdec-578ca2e619a6]]

View File

@@ -0,0 +1,508 @@
[[Property:title|Eiffel programming language reserved words]]
[[Property:link_title|Reserved words]]
[[Property:weight|1]]
[[Property:uuid|047ce062-45de-f25c-f356-ee8ec0fc2d1d]]
In the Eiffel programming language, there are certain words that are considered "reserved". These words have specific meanings recognized by the compiler. As such, it is invalid to attempt to use a reserved word as an ordinary language identifier.
The reserved words listed in the ISO/ECMA standard are shown below with a brief explanation of their meanings. Links are given where appropriate to the syntax definitions and to descriptions in the online documentation. Occasionally, references to the June 2006 standard document are used and are recognizable as clause numbers in parentheses, i.e., three integers separated by dots, for example: (8.14.1)
{{info|The list below includes all the Eiffel reserved words. Some of these words are considered ''language keywords'' while others are not. The distinction is that language keywords are reserved words that are used only as syntactical markers, and have no inherent semantic value. Examples are the keywords <code>do</code> and <code>end</code>. Non-keyword reserved words are those that do carry semantic value, such as <code>True</code> and <code>Current</code>.}}
{{note|The set of reserved words supported by the Eiffel Software implementation may vary somewhat from those specified in the current standard. See the [[Differences between standard ECMA-367 and Eiffel Software implementation|"differences" chapter of the online documentation]] for information on these variances.}}
==Reserved words==
===across===
Introduces an [[ET: Instructions#Loop|iteration]].
===agent===
Used to specify an [[ET: Agents|agent]].
:[[Eiffel programming language syntax#Agents|Syntax.]]
===alias===
Used to identify an alternative or alias feature name.
:[[Eiffel programming language syntax#Feature names|Syntax.]]
[[ET: The Dynamic Structure: Execution Model#Infix and prefix notations|Usage for infix/prefix notations.]]
[[ET: The Static Picture: System Organization#External software|Usage in interfaces to external software.]]
:[[Eiffel programming language syntax#External routines|Syntax.]]
===all===
Used in [[ET: Inheritance#Changing the export status|export adaptation]] to indicate that a chosen export status applies to all features inherited from a given parent.
:[[Eiffel programming language syntax#Export adaptation|Syntax.]]
===and===
The logical conjunction [[Eiffel programming language syntax#Operators|operator]]. Strict when used alone, nonstrict when used with [[#then|then]].
===as===
Used when [[ET: Inheritance#Multiple inheritance and renaming|renaming]] features in descendant classes.
:[[Eiffel programming language syntax#Rename clauses|Syntax.]]
===assign===
Used to designate [[ET: The Dynamic Structure: Execution Model#Abstraction|assigner commands]].
:[[Eiffel programming language syntax#Assigner marks|Syntax.]]
===attribute===
Introduces an attribute body, as in [[Void-safety: Background, definition, and tools#Self-initializing attributes|self-initializing attributes]].
:[[Eiffel programming language syntax#Attribute bodies|Syntax.]]
===check===
Identifies a [[ET: Other Mechanisms#Check|check instruction]].
:[[Eiffel programming language syntax#Check instructions|Syntax.]]
===class===
Used in a class header in the declaration of a [[ET: The Dynamic Structure: Execution Model#A simple class|class]].
:[[Eiffel programming language syntax#Class headers|Class header syntax.]]
===convert===
Used in converter clauses.
:[[Eiffel programming language syntax#Converter clauses|Syntax.]]
Used in feature names for operator aliases, supporting mixed type expressions causing a conversion of the target (8.5.14).
:[[Eiffel programming language syntax#Feature names|Syntax.]]
===create===
In the creators part of a class, introduces those procedures which can be used to [[ET: The Dynamic Structure: Execution Model#Creating and initializing objects|initialize instances]].
:[[Eiffel programming language syntax#Creators parts|Syntax.]]
Introduces a [[ET: The Dynamic Structure: Execution Model#Creating and initializing objects|creation instruction]].
:[[Eiffel programming language syntax#Creation instructions|Syntax.]]
Introduces a creation expression (8.20.18)
:[[Eiffel programming language syntax#Creation expressions|Syntax.]]
In [[ET: Inheritance#Constrained genericity|constrained genericity]], introduces a list of names of features which can be used as creation procedures with a generic class for a particular formal generic parameter. (8.12.10)
:[[Eiffel programming language syntax#Generic constraints|Syntax.]]
===Current===
A predefined entity indicating the current object.
:[[Eiffel programming language syntax#Entities and variables|Entity syntax.]]
:[[Eiffel programming language syntax#Types|Anchored types syntax.]]
===debug===
Introduces a [[ET: Other Mechanisms#Debug|debug instruction]].
:[[Eiffel programming language syntax#Debug Instructions|Syntax.]]
===deferred===
Used in class header to indicate a [[ET: Inheritance#Deferred features and classes|deferred class]].
:[[Eiffel programming language syntax#Class headers|Syntax.]]
Used in routine body to indicate a [[ET: Inheritance#Deferred features and classes|deferred feature]].
:[[Eiffel programming language syntax#Routine bodies|Syntax.]]
===do===
Introduces a sequence of instructions as a routine body, as shown in the [[ET: Hello World|Hello World]] example.
:[[Eiffel programming language syntax#Routine bodies|Syntax.]]
===else===
Used in [[ET: Other Mechanisms#Conditional|conditional]] and [[ET: Other Mechanisms#Multi-branch|multi-branch]] instructions to introduce a sequence of instructions to be executed in the case that no specified conditions are met.
:[[Eiffel programming language syntax#Conditionals|Conditional syntax.]]
:[[Eiffel programming language syntax#Multi-branch instructions|Multi-branch syntax.]]
Used as part of the double reserved word <code>or else</code>, the semi-strict disjunction operator.
:[[Eiffel programming language syntax#Operators|Syntax.]]
Used after the reserved word [[#require|<code>require</code>]] as a precondition extension, allowing the weakening of an inherited precondition (8.10.3).
:[[Eiffel programming language syntax#Assertions|Syntax.]]
===elseif===
Used in [[ET: Other Mechanisms#Conditional|conditional]] instructions to effect a "multi-branch" choice instruction.
:[[Eiffel programming language syntax#Conditionals|Syntax.]]
===end===
Serves to terminate several Eiffel programming language constructs.
:Syntax for:
::[[Eiffel programming language syntax#Class declarations|Class declarations]]
::[[Eiffel programming language syntax#Feature bodies|Feature bodies]]
::[[Eiffel programming language syntax#Inheritance parts|Inheritance parts]]
::[[Eiffel programming language syntax#Check instructions|Check instructions]]
::[[Eiffel programming language syntax#Generic constraints|Generic constraints: renaming and constraint creators]]
::[[Eiffel programming language syntax#Conditionals|Conditional instructions]]
::[[Eiffel programming language syntax#Multi-branch instructions|Multi-branch instructions]]
::[[Eiffel programming language syntax#Loops|Loops]]
::[[Eiffel programming language syntax#Debug instructions|Debug instructions]]
===ensure===
Introduces a [[ET: Design by Contract (tm), Assertions and Exceptions#Expressing assertions|postcondition]].
When followed by the reserved word [[#then|<code>then</code>]] denotes a postcondition extension, allowing the strengthening of an inherited postcondition (8.10.3).
:[[Eiffel programming language syntax#Assertions|Syntax.]]
===expanded===
Used in a class header to indicate that a class is [[ET: The Dynamic Structure: Execution Model#Type categories|expanded]].
:[[Eiffel programming language syntax#Class headers|Syntax.]]
===export===
Used to [[ET: Inheritance#Changing the export status|change the export status]] (availability to clients) of inherited features.
:[[Eiffel programming language syntax#Export adaptation|Syntax.]]
===external===
Denotes an [[ET: The Static Picture: System Organization#External software|external routine]]. External routines are commonly defined to interface with [[C externals|C external routines]] and [[C++ Externals|C++ external routines]].
:[[Eiffel programming language syntax#External routines|Syntax]]
===False===
Boolean manifest constant.
:[[Eiffel programming language syntax#Manifest constants|Syntax.]]
===feature===
Introduces a [[ET: Hello World|feature clause]].
:[[Eiffel programming language syntax#Feature parts|Syntax.]]
===from===
Used in [[ET: Other Mechanisms#Loop|loop]] initialization.
:[[Eiffel programming language syntax#Loops|Syntax.]]
===frozen===
Used in a class header to mark a class explicitly as frozen. A frozen class prohibits it from serving as a "conforming parent" to other classes. (8.4.5).
:[[Eiffel programming language syntax#Class headers|Syntax.]]
Used in a feature declaration to mark a feature as frozen. A frozen feature cannot be redefined by heir classes.
:[[Eiffel programming language syntax#New feature lists|Syntax.]]
Used with a formal generic parameter to indicate that conformance of generic derivations of the class require identical actual generic parameters. (8.12.3)
:[[Eiffel programming language syntax#Formal generic parameters|Syntax.]]
===if===
Introduces a [[ET: Other Mechanisms#Conditional|conditional]].
:[[Eiffel programming language syntax#Conditionals|Syntax.]]
===implies===
The semi-strict logical implication [[Eiffel programming language syntax#Operators|operator]].
===inherit===
Used in an [[ET: Inheritance|inherit]] clause.
:[[Eiffel programming language syntax#Inheritance parts|Syntax.]]
===inspect===
Introduces a [[ET: Other Mechanisms#Multi-branch|multi-branch]] instruction.
:[[Eiffel programming language syntax#Multi-branch instructions|Syntax.]]
===invariant===
Used to introduce an invariant assertion as a [[ET: Design by Contract (tm), Assertions and Exceptions#Class invariants|class invariant]] or [[ET: Instructions#Loop|loop invariant]].
:[[Eiffel programming language syntax#Assertions|Assertions syntax.]]
:[[Eiffel programming language syntax#Class declarations|Syntax of class declaration including class invariant.]]
:[[Eiffel programming language syntax#Loops|Syntax of loop including loop invariant.]]
===like===
Used in the declaration of an [[ET: Inheritance#Covariance and anchored declarations|anchored]] entity.
:[[Eiffel programming language syntax#Types|Syntax.]]
===local===
Introduces the [[ET: The Dynamic Structure: Execution Model#Entities|local variable]] declarations in a feature body.
:[[Eiffel programming language syntax#Feature bodies|Feature bodies syntax.]]
:[[Eiffel programming language syntax#Local variables|Local variable declarations syntax.]]
===loop===
Introduces a [[ET: Other Mechanisms#Loop|loop]] body.
:[[Eiffel programming language syntax#Loops|Syntax.]]
===not===
The logical negation [[Eiffel programming language syntax#Operators|operator]].
===note===
Used to begin a Notes part, in a [[Eiffel programming language syntax#Class declarations|class declaration]], a [[Eiffel programming language syntax#Feature declarations|feature declaration]], or a [[Eiffel programming language syntax#Check instructions|check instruction]].
:[[Eiffel programming language syntax#Notes|Syntax.]]
===obsolete===
Used to mark [[ET: Other Mechanisms#Obsolete features and classes|obsolete features and classes]].
:[[Eiffel programming language syntax#Feature declarations|Feature declarations syntax.]]
:[[Eiffel programming language syntax#Class declarations|Class declarations declarations syntax.]]
:[[Eiffel programming language syntax#Obsolete marks|Obsolete mark syntax.]]
===old===
Introduces an ''old expression''. Old expressions are valid only in the [[ET: Design by Contract (tm), Assertions and Exceptions#Postconditions|postconditions]] of routines.
:[[Eiffel programming language syntax#Old postcondition expressions|Syntax.]]
===once===
Used to introduce [[ET: Other Mechanisms#Once routines and shared objects|once routines]] and once string expressions.
:[[Eiffel programming language syntax#Routine bodies|Once routine syntax.]]
:[[Eiffel programming language syntax#Expressions|Once string syntax.]]
===only===
Used in an ''only postcondition clause''. (8.9.11)
:[[Eiffel programming language syntax#"Old" postcondition expressions|Syntax.]]
===or===
The logical disjunction [[Eiffel programming language syntax#Operators|operator]]. Strict when used alone, nonstrict when used with [[#else|else]].
===Precursor===
Allows a redefined routine to access the routine it redefines, i.e, its [[ET: Inheritance#Redefinition|precursor]].
:[[Eiffel programming language syntax#Precursor|Syntax.]]
===redefine===
Used in an [[Eiffel programming language syntax#Inheritance parts|inheritance part]] of a [[Eiffel programming language syntax#Class declarations|class declaration]] to list those inherited features which, in the heir class, will receive new implementations, specifications, or both, i.e, those features being [[ET: Inheritance#Redefinition|redefined]].
:[[Eiffel programming language syntax#Redefinition|Redefine syntax.]]
===rename===
Used in an [[Eiffel programming language syntax#Inheritance parts|inheritance part]] of a [[Eiffel programming language syntax#Class declarations|class declaration]] to [[ET: Inheritance#Multiple inheritance and renaming|provide alternative names]] for inherited features in an heir class.
Used to rename features in a [[Eiffel programming language syntax#Generic constraints|generic constraint]]. (8.12.8).
:[[Eiffel programming language syntax#Rename clauses|Syntax.]]
===require===
Introduces a [[ET: Design by Contract (tm), Assertions and Exceptions#Expressing assertions|precondition]].
When followed by the reserved word [[#else|<code>else</code>]] denotes a precondition extension, allowing the weakening of an inherited precondition (8.10.3).
:[[Eiffel programming language syntax#Assertions|Syntax.]]
===rescue===
Introduces a [[ET: Design by Contract (tm), Assertions and Exceptions#Exception handling|rescue clause]] in a [[Eiffel programming language syntax#Feature bodies|feature body]].
:[[Eiffel programming language syntax#Rescue clauses|Syntax.]]
===Result===
A predefined [[ET: The Dynamic Structure: Execution Model#Entities|entity]] used to represent the final result of a function.
:[[Eiffel programming language syntax#Entities and variables|Syntax.]]
===retry===
An [[Eiffel programming language syntax#Instructions|instruction]] valid only in [[Eiffel programming language syntax#Rescue clauses|rescue clauses]] and used to [[ET: Design by Contract (tm), Assertions and Exceptions#Exception handling|re-execute the routine]] in which it appears.
:[[Eiffel programming language syntax#Rescue clauses|Syntax.]]
===select===
Used in an [[Eiffel programming language syntax#Inheritance parts|inheritance part]] of a [[Eiffel programming language syntax#Class declarations|class declaration]] to resolve possible ambiguities related to polymorphism and dynamic binding in the presence of [[ET: Inheritance#Repeated inheritance and selection|repeated inheritance]].
:[[Eiffel programming language syntax#Select clauses|Syntax.]]
===separate===
Reserved for future use.
{{Note|Used in EiffelStudio implementations version 6.8 and later to support [[Concurrent programming with SCOOP]].}}
===then===
Used in [[ET: Other Mechanisms#Conditional|conditional]] and [[ET: Other Mechanisms#Multi-branch|multi-branch]] instructions to introduce a sequence of instructions to be executed in the case that a condition is met.
:[[Eiffel programming language syntax#Conditionals|Conditional syntax.]]
:[[Eiffel programming language syntax#Multi-branch instructions|Multi-branch syntax.]]
Used as part of the double reserved word <code>and then</code>, the semi-strict conjunction operator.
:[[Eiffel programming language syntax#Operators|Syntax.]]
Used after the reserved word [[#ensure|<code>ensure</code>]] as a postcondition extension, allowing the strengthening of an inherited postcondition (8.10.3).
:[[Eiffel programming language syntax#Assertions|Syntax.]]
===True===
Boolean manifest constant.
:[[Eiffel programming language syntax#Manifest constants|Syntax.]]
===TUPLE===
Denotes a [[ET: Other Mechanisms#Tuple types|TUPLE type]].
:[[Eiffel programming language syntax#Tuple types|Syntax.]]
===undefine===
Used in an [[Eiffel programming language syntax#Inheritance parts|inheritance part]] of a [[Eiffel programming language syntax#Class declarations|class declaration]] to [[ET: Inheritance#Joining and uneffecting|uneffect]] an inherited feature.
:[[Eiffel programming language syntax#Undefine clauses|Syntax.]]
===until===
Used in [[ET: Other Mechanisms#Loop|loop]] initialization.
:[[Eiffel programming language syntax#Loops|Syntax.]]
===variant===
Introduces a [[ET: Instructions#Loop|loop variant]].
:[[Eiffel programming language syntax#Variants|Syntax.]]
===Void===
A predefined entity name representing a [[ET: The Dynamic Structure: Execution Model#Basic operations|void (a.k.a., null) reference]].
===when===
Used in a [[ET: Other Mechanisms#Multi-branch|multi-branch instruction]] to introduce cases.
:[[Eiffel programming language syntax#Multi-branch instructions|Syntax.]]
===xor===
The exclusive disjunction [[Eiffel programming language syntax#Operators|operator]].

View File

@@ -0,0 +1,765 @@
[[Property:title|Eiffel programming language syntax]]
[[Property:link_title|Syntax]]
[[Property:weight|0]]
[[Property:uuid|4CB56AD5-1586-41F6-9E81-085F47E992DC]]
The syntax specification shown here is a less complete and less formal version of that which is in the Eiffel ISO/ECMA standard document. The format is BNF-E. The Language Specification section of the standard document includes an overview of BNF-E.
There are a few parts of the syntax that are either non-production or non-representable in BNF-E. Some of these have been omitted from the following specification. These omitted parts of the syntax definition add to the precision of the specification, but knowledge of them is not always vital for developers.
In the BNF-E representation, generally non-terminals which are defined in the same group of productions in which they are used are not linked. However when a non-terminal is defined outside a group in which it is used, it is linked to the group in which it is defined.
__TOC__
The following section contains those non-production elements of the specification that are used later in the BNF-E specification.
==Eiffel non-production elements==
===Identifiers===
An '''identifier''' is a sequence of one or more alphanumeric [[#Characters|characters]] of which the first is a letter.
The definition is augmented by the rule that Identifiers are not valid if they are the same as one of the language's reserved words.
===Characters===
Characters are either:
* All 32-bit, corresponding to Unicode and to the Eiffel type CHARACTER_32.
* All 8-bit, corresponding to 8-bit extended ASCII and to the Eiffel type CHARACTER_8
===Reals===
A real -- specimen of Real -- is made of the following elements, in the order given:
* An optional decimal [[#Integers|Integer]], giving the integral part.
* A required "." (dot).
* An optional decimal [[#Integers|Integer]], giving the fractional part.
* An optional exponent, which is the letter ''e'' or ''E'' followed by an optional [[#Manifest constants|Sign]] and a decimal [[#Integers|Integer]].
No intervening character (blank or otherwise) is permitted between these elements. The integral and fractional parts may not both be absent.
===Strings===
A string -- specimen of construct String -- is a sequence of zero or more manifest characters.
===Simple strings===
A simple string -- specimen of Simple_string -- is a [[#Strings|String]] consisting of at most one line (that is to say, containing no embedded new-line manifest character), possibly containing [[#Special characters|codes for special characters]].
===Special characters===
{| border="2"
|+ Special Characters and Their Codes
|-
! Character
! Code
! Mnemonic name
|-
| @ || %A || At-sign
|-
| BS || %B || Backspace
|-
| ^ || %C || Circumflex
|-
| $ || %D || Dollar
|-
| FF || %F || Form feed
|-
| \ || %H || Backslash
|-
| ~ || %L || Tilde
|-
| NL (LF) || %N || Newline
|-
| `` ` `` || %Q || Backquote
|-
| CR || %R || Carriage return
|-
| # || %S || Sharp
|-
| HT || %T || Horizontal tab
|-
| NUL || %U || Null
|-
| &#124; || %V || Vertical bar
|-
| % || %% || Percent
|-
| ' || %' || Single quote
|-
| " || %" || Double quote
|-
| [ || %( || Opening bracket
|-
| ] || %) || Closing bracket
|-
| { || %< || Opening brace
|-
| } || %> || Closing brace
|}
* %/123/ represents the character with decimal code 123 .
===Line wrapping parts===
A sequence of characters consisting of the following, in order:
* % (percent character)
* Zero or more blanks or tabs
* New line (Line feed)
* Zero or more blanks or tabs
* % (percent character)
Line wrapping parts are used as separators between one [[#Simple strings|Simple_string]] and the next in a [[#Manifest strings|Basic_manifest_string]] so that the string can be split across lines.
==Eiffel BNF-E Syntax==
===Class names ===
Class_name ::= [[#Identfiers|Identifier]]
===Class declarations ===
Class_declaration ::= <nowiki>[</nowiki>[[#Notes|Notes]]<nowiki>]</nowiki>
[[#Class headers|Class_header]] <nowiki>[</nowiki>[[#Formal generic parameters|Formal_generics]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Obsolete marks|Obsolete]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Inheritance parts|Inheritance]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Creators parts|Creators]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Converter clauses|Converters]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Feature parts|Features]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Notes|Notes]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Assertions|Invariant]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Notes|Notes]]<nowiki>]</nowiki>
<code>end</code>
===Notes ===
Notes ::= <code>note</code> Note_list
Note_list ::= {Note_entry ";" ...}*
Note_entry ::= Note_name Note_values
Note_name ::= [[#Identifiers|Identifier]] ":"
Note_values ::= {Note_item ","...}+
Note_item ::= [[#Identifiers|Identifier]] | [[#Manifest constants|Manifest_constant]]
===Class headers ===
Class_header ::= <nowiki>[Header_mark]</nowiki> <code>class</code> [[#Class names|Class_name]]
Header_mark ::= <code>deferred</code> | <code>expanded</code> | <code>frozen</code>
===Obsolete marks ===
Obsolete ::= <code>obsolete</code> Message
Message ::= [[#Manifest strings|Manifest_string]]
===Feature parts ===
Features ::= Feature_clause+
Feature_clause ::= <code>feature</code> <nowiki>[</nowiki>[[#Clients|Clients]]<nowiki>]</nowiki> <nowiki>[</nowiki>[[#Feature parts|Header_comment]]<nowiki>]</nowiki> Feature_declaration_list
Feature_declaration_list ::= {[[#Feature declarations|Feature_declaration]] ";" ...}*
Header_comment ::= [[#Comments|Comment]]
===Feature declarations ===
Feature_declaration ::= [[#New feature lists|New_feature_list]] Declaration_body
Declaration_body ::= <nowiki>[</nowiki>[[#Formal argument and entity declarations|Formal_arguments]]<nowiki>] [Query_mark] [Feature_value] </nowiki>
Query_mark ::= Type_mark <nowiki>[</nowiki>[[#Assigner marks|Assigner_mark]]<nowiki>]</nowiki>
Type_mark ::= ":" [[#Types|Type]]
Feature_value ::= <nowiki>[Explicit_value] </nowiki>
<nowiki>[</nowiki>[[#Obsolete parts|Obsolete]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Feature parts|Header_comment]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Feature bodies|Attribute_or_routine]]<nowiki>]</nowiki>
Explicit_value ::= "=" [[#Manifest constants|Manifest_constant]]
===New feature lists ===
New_feature_list ::= {New_feature "," ...}+
New_feature ::= <nowiki>[</nowiki><code>frozen</code><nowiki>]</nowiki> [[#Feature names|Extended_feature_name]]
===Feature bodies ===
Attribute_or_routine ::= <nowiki>[</nowiki>[[#Assertions|Precondition]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Local variable declarations|Local_declarations]]<nowiki>]</nowiki>
Feature_body
<nowiki>[</nowiki>[[#Assertions|Postcondition]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Rescue clauses|Rescue]]<nowiki>]</nowiki>
<code>end</code>
Feature_body ::= [[#Routine bodies|Deferred]] | [[#Routine bodies|Effective_routine]] | [[#Attribute bodies|Attribute]]
===Feature names ===
Extended_feature_name ::= Feature_name <nowiki>[Alias]</nowiki>
Feature_name ::= [[#Identfiers|Identifier]]
Alias ::= <code>alias</code> '"' Alias_name '"' <nowiki>[</nowiki><code>convert</code><nowiki>]</nowiki>
Alias_name ::= [[#Operators|Operator]] | Bracket
Bracket ::= "<nowiki>[ ]</nowiki>"
===Operators ===
Operator ::= Unary | Binary
Unary ::= <code>not</code> | "+" | "-" | Free_unary
Binary ::= <nowiki>"+" | "-" | "*" | "/" | "//" | "\\" | "^" | ".." | "<" | ">" | "<=" | ">=" |</nowiki> <code>and</code> | <code>or</code> | <code>xor</code> | <code>and</code> <code>then</code> | <code>or</code> <code>else</code> | <code>implies</code> | Free_binary
{{note| Free_unary and Free_binary are free operators that are distinct from (respectively) the ''standard'' unary and binary operators (one- or two-character symbols) explicitly listed in the Unary and Binary productions. See ''Definition: Free operator'' in the standard for more precision.}}
===Assigner marks ===
Assigner_mark ::= <code>assign</code> [[#Feature names|Feature_name]]
===Inheritance parts ===
Inheritance ::= Inherit_clause+
Inherit_clause ::= <code>inherit</code> <nowiki>[Non_conformance]</nowiki> Parent_list
Non_conformance ::= "{" NONE "}"
Parent_list ::= {Parent ";" ...}+
Parent ::= [[#Types|Class_type]] <nowiki>[Feature_adaptation]</nowiki>
Feature_adaptation ::= <nowiki>[</nowiki>[[#Undefine clauses|Undefine]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Redefinition|Redefine]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Rename clauses|Rename]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Export adaptation|New_exports]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Select clauses|Select]]<nowiki>]</nowiki>
<code>end</code>
===Rename clauses ===
Rename ::= <code>rename</code> Rename_list
Rename_list ::= {Rename_pair "," ...}+
Rename_pair ::= [[#Feature names|Feature_name]] <code>as</code> [[#Feature names|Extended_feature_name]]
===Clients ===
Clients ::= "{" Class_list "}"
Class_list ::= {[[#Class names|Class_name]] "," ...}+
===Export adaptation ===
New_exports ::= <code>export</code> New_export_list
New_export_list ::= {New_export_item ";" ...}+
New_export_item ::= [[#Clients|Clients]] <nowiki>[</nowiki>[[#Feature parts|Header_comment]]<nowiki>]</nowiki> Feature_set
Feature_set ::= Feature_list | <code>all</code>
Feature_list ::= {[[#Feature names|Feature_name]] "," ...}+
===Formal argument and entity declarations ===
Formal_arguments ::= "(" [[#Formal argument and entity declarations|Entity_declaration_list]] ")"
Entity_declaration_list ::= {Entity_declaration_group ";" ...}+
Entity_declaration_group ::= Identifier_list [[#Feature declarations|Type_mark]]
Identifier_list ::= {[[#Identfiers|Identifier]] "," ...}+
===Routine bodies ===
Deferred ::= <code>deferred</code>
Effective_routine ::= Internal | [[#External routines|External]]
Internal ::= Routine_mark [[#Instructions|Compound]]
Routine_mark ::= <code>do</code> | Once
Once ::= <code>once</code> <nowiki>[</nowiki> "("Key_list ")" <nowiki>]</nowiki>
Key_list ::= {[[#Manifest strings|Manifest_string]] "," ...}+
===Local variable declarations ===
Local_declarations ::= <code>local</code> <nowiki>[</nowiki>[[#Formal argument and entity declarations|Entity_declaration_list]]<nowiki>]</nowiki>
===Instructions ===
Compound ::= {Instruction ";" ...}*
Instruction ::= [[#Creation instructions|Creation_instruction]] | [[#Feature calls|Call]] | [[#Assignments|Assignment]] | [[#Assigner calls|Assigner_call]] | [[#Conditionals|Conditional]] | [[#Multi-branch instructions|Multi_branch]]
| [[#Loops|Loop]] | [[#Debug instructions|Debug]] | [[#Precursor|Precursor]] | [[#Check instructions|Check]] | [[#Rescue clauses|Retry]]
===Assertions ===
Precondition ::= <code>require</code> <nowiki>[</nowiki><code>else</code><nowiki>]</nowiki> Assertion
Postcondition ::= <code>ensure</code> <nowiki>[</nowiki><code>then</code><nowiki>]</nowiki> Assertion <nowiki>[</nowiki>[[#"Only" postcondition clauses|Only]]<nowiki>]</nowiki>
Invariant ::= <code>invariant</code> Assertion
Assertion ::= {Assertion_clause ";" ...}*
Assertion_clause ::= <nowiki>[</nowiki>Tag_mark<nowiki>]</nowiki> Unlabeled_assertion_clause
Unlabeled_assertion_clause ::= [[#Expressions|Boolean_expression]] | [[#Comments|Comment]]
Tag_mark ::= Tag ":"
Tag ::= [[#Identfiers|Identifier]]
==="Old" postcondition expressions ===
Old ::= <code>old</code> [[#Expressions|Expression]]
==="Only" postcondition clauses ===
Only ::= <code>only</code> <nowiki>[</nowiki>[[#Export adaptation|Feature_list]]<nowiki>]</nowiki>
===Check instructions ===
Check ::= <code>check</code> [[#Assertions|Assertion]] <nowiki>[</nowiki>[[#Notes|Notes]]<nowiki>]</nowiki> <code>end</code>
===Variants ===
Variant ::= <code>variant</code> <nowiki>[</nowiki>[[#Assertions|Tag_mark]]<nowiki>]</nowiki> [[#Expressions|Expression]]
===Precursor ===
Precursor ::= <code>Precursor</code> [Parent_qualification] <nowiki>[</nowiki>[[#Actual arguments|Actuals]]<nowiki>]</nowiki>
Parent_qualification ::= "{" [[#Class names|Class_name]] "}"
===Redefinition ===
Redefine ::= <code>redefine</code> [[#Export adaptation|Feature_list]]
===Undefine clauses ===
Undefine ::= <code>undefine</code> [[#Export adaptation|Feature_list]]
===Types ===
Type ::= Class_or_tuple_type | [[#Formal generic parameters|Formal_generic_name]] | Anchored
Class_or_tuple_type ::= Class_type | [[#Tuple types|Tuple_type]]
Class_type ::= [Attachment_mark] [[#Class names|Class_name]] <nowiki>[</nowiki>[[#Actual generic parameters|Actual_generics]]<nowiki>]</nowiki>
Attachment_mark ::= "?" | "!"
Anchored ::= [Attachment_mark] <code>like</code> Anchor
Anchor ::= [[#Feature names|Feature_name]] | <code>Current</code>
===Actual generic parameters ===
Actual_generics ::= <nowiki>"[" Type_list "]"</nowiki>
Type_list ::= {[[#Types|Type]] "," ...}+
===Formal generic parameters ===
Formal_generics ::= <nowiki>"[" Formal_generic_list "]"</nowiki>
Formal_generic_list ::= {Formal_generic ","...}+
Formal_generic ::= <nowiki>[</nowiki><code>frozen</code><nowiki>]</nowiki> Formal_generic_name <nowiki>[</nowiki>[[#Generic constraints|Constraint]]<nowiki>]</nowiki>
Formal_generic_name ::= <nowiki>[?]</nowiki> [[#Identfiers|Identifier]]
===Generic constraints ===
Constraint ::= "->" Constraining_types <nowiki>[Constraint_creators]</nowiki>
Constraining_types ::= Single_constraint | Multiple_constraint
Single_constraint ::= [[#Types|Type]] [Renaming]
Renaming ::= [[#Rename clauses|Rename]] <code>end</code>
Multiple_constraint ::= "{" Constraint_list "}"
Constraint_list ::= {Single_constraint "," ...}+
Constraint_creators ::= <code>create</code> [[#Export adaptation|Feature_list]] <code>end</code>
===Tuple types ===
Tuple_type ::= <code>TUPLE</code> <nowiki>[Tuple_parameter_list]</nowiki>
Tuple_parameter_list ::= <nowiki>"[" Tuple_parameters "]"</nowiki>
Tuple_parameters ::= [[#Actual generic parameters|Type_list]] | [[#Formal argument and entity declarations|Entity_declaration_list]]
===Manifest tuples ===
Manifest_tuple ::= <nowiki>"[" Expression_list "]"</nowiki>
Expression_list ::= {[[#Expressions|Expression]] "," ...}*
===Converter clauses ===
Converters ::= <code>convert</code> Converter_list
Converter_list ::= {Converter ","...}+
Converter ::= Conversion_procedure | Conversion_query
Conversion_procedure ::= [[#Feature names|Feature_name]] "(" "{" [[#Actual generic parameters|Type_list]] "}" ")"
Conversion_query ::= [[#Feature names|Feature_name]] ":" "{" [[#Actual generic parameters|Type_list]] "}"
===Select clauses ===
Select ::= <code>select</code> [[#Export adaptation|Feature_list]]
===Conditionals ===
Conditional ::= <code>if</code> Then_part_list <nowiki>[Else_part]</nowiki> <code>end</code>
Then_part_list ::= {Then_part <code>elseif</code> ...}+
Then_part ::= [[#Expressions|Boolean_expression]] <code>then</code> [[#Instructions|Compound]]
Else_part ::= <code>else</code> [[#Instructions|Compound]]
===Multi-branch instructions ===
Multi_branch ::= <code>inspect</code> [[#Expressions|Expression]] <nowiki>[When_part_list] [Else_part]</nowiki> <code>end</code>
When_part_list ::= When_part+
When_part ::= <code>when</code> Choices <code>then</code> [[#Instructions|Compound]]
Choices ::= {Choice "," ...}+
Choice ::= [[#Constants|Constant]] | [[#Manifest constants|Manifest_type]] | Constant_interval | Type_interval
Constant_interval ::= [[#Constants|Constant]] ".." [[#Constants|Constant]]
Type_interval ::= [[#Manifest constants|Manifest_type]] ".." [[#Manifest constants|Manifest_type]]
===Loops ===
Loop ::=<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<nowiki>[</nowiki>Iteration<nowiki>]</nowiki><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<nowiki>[</nowiki>Initialization<nowiki>]</nowiki><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<nowiki>[</nowiki>[[#Assertions|Invariant]]<nowiki>]</nowiki><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<nowiki>[</nowiki>Exit_condition<nowiki>]</nowiki><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Loop_body<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<nowiki>[</nowiki>[[#Variants|Variant]]<nowiki>]</nowiki><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>end</code>
Iteration ::= <code>across</code> [[#Expressions|Expression]] <code>as</code> [[#Identfiers|Identifier]]
Initialization ::= <code>from</code> [[#Instructions|Compound]]
Exit_condition ::= <code>until</code> [[#Expressions|Boolean_expression]]
Loop_body ::=<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>loop</code> [[#Instructions|Compound]] |<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>all</code> [[#Expressions|Boolean_expression]] |<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>some</code> [[#Expressions|Boolean_expression]]
===Debug instructions ===
Debug ::= <code>debug</code> <nowiki>[</nowiki> "("[[#Routine_bodies|Key_list]] ")" ] [[#Instructions|Compound]] <code>end</code>
===Attribute bodies ===
Attribute ::= <code>attribute</code> [[#Instructions|Compound]]
===Entities and variables ===
Entity ::= Variable | Read_only
Variable ::= Variable_attribute | Local
Variable_attribute ::= [[#Feature names|Feature_name]]
Local ::= [[#Identfiers|Identifier]] | <code>Result</code>
Read_only ::= Formal | Constant_attribute | <code>Current</code>
Formal ::= [[#Identfiers|Identifier]]
Constant_attribute ::= [[#Feature names|Feature_name]]
===Creators parts ===
Creators ::= Creation_clause+
Creation_clause ::= <code>create</code> <nowiki>[</nowiki>[[#Clients|Clients]]<nowiki>]</nowiki> <nowiki>[</nowiki>[[#Feature parts|Header_comment]]<nowiki>]</nowiki> Creation_procedure_list
Creation_procedure_list ::= {Creation_procedure ","...}+
Creation_procedure ::= [[#Feature names|Feature_name]]
===Creation instructions ===
Creation_instruction ::= <code>create</code> <nowiki>[Explicit_creation_type]</nowiki> Creation_call
Explicit_creation_type ::= "{" [[#Types|Type]] "}"
Creation_call ::= [[#Entities and variables|Variable]] [Explicit_creation_call]
Explicit_creation_call ::= "." [[#Feature calls|Unqualified_call]]
===Creation expressions ===
Creation_expression ::= <code>create</code> [[#Creation instructions|Explicit_creation_type]] <nowiki>[</nowiki>[[#Creation instructions|Explicit_creation_call]]<nowiki>]</nowiki>
===Equality expressions ===
Equality ::= [[#Expressions|Expression]] Comparison [[#Expressions|Expression]]
Comparison ::= "=" | "/=" | "~" | "/~"
===Assignments ===
Assignment ::= [[#Entities and variables|Variable]] ":=" [[#Expressions|Expression]]
===Assigner calls ===
Assigner_call ::= [[#Expressions|Expression]] ":=" [[#Expressions|Expression]]
===Feature calls ===
Call ::= Object_call | Non_object_call
Object_call ::= <nowiki>[Target "."] Unqualified_call </nowiki>
Unqualified_call ::= [[#Feature names|Feature_name]] <nowiki>[</nowiki>[[#Actual arguments|Actuals]]<nowiki>]</nowiki>
Target ::= [[#Entities and variables|Local]] | [[#Entities and variables|Read_only]] | Call | Parenthesized_target
Parenthesized_target ::= "( |" [[#Expressions|Expression]] "| )"
Non_object_call ::= "{" [[#Types|Type]] "}" "." Unqualified_call
===Actual arguments ===
Actuals ::= "(" Actual_list ")"
Actual_list ::= {[[#Expressions|Expression]] "," ...}+
===Object test ===
Object_test ::= "{" [[#Identfiers|Identifier]] ":" [[#Types|Type]] "}" [[#Expressions|Expression]]
===Rescue clauses ===
Rescue ::= <code>rescue</code> [[#Instructions|Compound]]
Retry ::= <code>retry</code>
===Agents ===
Agent ::= Call_agent | Inline_agent
Call_agent ::= <code>agent</code> [[#Call agent bodies|Call_agent_body]]
Inline_agent ::= <code>agent</code> <nowiki>[</nowiki>[[#Formal argument and entity declarations|Formal_arguments]]<nowiki>]</nowiki> <nowiki>[</nowiki>[[#Feature declarations|Type_mark]]<nowiki>]</nowiki> <nowiki>[</nowiki>[[#Feature bodies|Attribute_or_routine]]<nowiki>]</nowiki> <nowiki>[</nowiki>[[#Call agent bodies|Agent_actuals]]<nowiki>]</nowiki>
===Call agent bodies ===
Call_agent_body ::= Agent_qualified | Agent_unqualified
Agent_qualified ::= Agent_target ". " Agent_unqualified
Agent_unqualified ::= [[#Feature names|Feature_name]] [Agent_actuals]
Agent_target ::= Entity | Parenthesized | [[#Manifest constants|Manifest_type]]
Agent_actuals ::= "(" Agent_actual_list ")"
Agent_actual_list ::= {Agent_actual "," ...}+
Agent_actual ::= [[#Expressions|Expression]] | Placeholder
Placeholder ::= <nowiki>[</nowiki>[[#Manifest constants|Manifest_type]]<nowiki>]</nowiki> "?"
===Expressions ===
Expression ::= Basic_expression | Special_expression
Basic_expression ::= [[#Entities and variables|Read_only]] | [[#Entities and variables|Local]] | [[#Feature calls|Call]] | [[#Precursor|Precursor]] | [[#Equality expressions|Equality]] | Parenthesized | [[#"Old" postcondition expressions|Old]] |
[[#Operator expressions|Operator_expression]] | [[#Bracket expressions|Bracket_expression]] | [[#Creation expression|Creation_expression]]
Special_expression ::= [[#Manifest constants|Manifest_constant]] | [[#Manifest tuples|Manifest_tuple]] | [[#Agents|Agent]] | [[#Object test|Object_test]] | Once_string |
Address
Parenthesized ::= "(" Expression ")"
Address ::= "$" [[#Entities and variables|Variable]]
Once_string ::= <code>once</code> [[#Manifest strings|Manifest_string]]
Boolean_expression ::= Basic_expression | [[#Manifest constants|Boolean_constant]] | [[#Object test|Object_test]]
===Operator expressions ===
Operator_expression ::= Unary_expression | Binary_expression
Unary_expression ::= Unary Expression
Binary_expression ::= [[#Expressions|Expression]] [[#Operators|Binary]] [[#Expressions|Expression]]
===Bracket expressions ===
Bracket_expression ::= Bracket_target "[" [[#Actual arguments|Actuals]] "]"
Bracket_target ::= [[#Feature calls|Target]] | [[#Expressions|Once_string]] | [[#Manifest constants|Manifest_constant]] | [[#Manifest tuples|Manifest_tuple]]
===Constants ===
Constant ::= [[#Manifest constants|Manifest_constant]] | Constant_attribute
Constant_attribute ::= [[#Feature names|Feature_name]]
===Manifest constants ===
Manifest_constant ::= [Manifest_type] Manifest_value
Manifest_type ::= "{" [[#Types|Type]] "}"
Manifest_value ::= Boolean_constant |
Character_constant |
Integer_constant |
Real_constant |
[[#Manifest strings|Manifest_string]] |
Manifest_type
Sign ::= "+" | "-"
Integer_constant ::= <nowiki>[Sign]</nowiki> [[#Integers|Integer]]
Character_constant ::= " ' " [[#Characters|Character]] " ' "
Boolean_constant ::= <code>True</code> | <code>False</code>
Real_constant ::= <nowiki>[Sign]</nowiki> [[#Reals|Real]]
===Manifest strings ===
Manifest_string ::= Basic_manifest_string | Verbatim_string
Basic_manifest_string ::= ' " ' String_content ' " '
String_content ::= {[[#Simple strings|Simple_string]] [[#Line wrapping parts|Line_wrapping_part]] ...}+
Verbatim_string ::= Verbatim_string_opener Line_sequence Verbatim_string_closer
Verbatim_string_opener ::= ' " ' <nowiki>[</nowiki>[[#Simple strings|Simple_string]]<nowiki>]</nowiki> Open_bracket
Verbatim_string_closer ::= Close_bracket <nowiki>[</nowiki>[[#Simple strings|Simple_string]]<nowiki>]</nowiki> ' " '
Open_bracket ::= <nowiki>"[" | "{"</nowiki>
Close_bracket ::= "]" | "}"Verbatim_string ::= Verbatim_string_opener Line_sequence Verbatim_string_closer
Verbatim_string_opener ::= ' " ' <nowiki>[</nowiki>[[#Simple strings|Simple_string]]<nowiki>]</nowiki> Open_bracket
Verbatim_string_closer ::= Close_bracket <nowiki>[</nowiki>[[#Simple strings|Simple_string]]<nowiki>]</nowiki> ' " '
Open_bracket ::= <nowiki>"[" | "{" </nowiki>
Close_bracket ::= <nowiki>"]" | "}" </nowiki>
===External routines ===
External ::= <code>external</code> External_language <nowiki>[External_name]</nowiki>
External_language ::= Unregistered_language | [[#Registered languages|Registered_language]]
Unregistered_language ::= [[#Manifest strings|Manifest_string]]
External_name ::= <code>alias</code> [[#Manifest strings|Manifest_string]]
{{note|If the `inline` keyword is used in the Registered_language part, then External_name part is the inline code on the specified language.}}
===Registered languages ===
Registered_language ::= [[#C externals|C_external]] | [[#C++ externals|C++_external]] | [[#DLL externals|DLL_external]]
===External signatures ===
External_signature ::= <code>signature</code> <nowiki>[External_argument_types] [: External_type]</nowiki>
External_argument_types ::= "(" External_type_list ")"
External_type_list ::= {External_type "," ...}*
External_type ::= [[#Simple strings|Simple_string]]
===External file use ===
External_file_use ::= <code>use</code> External_file_list
External_file_list ::= {External_file "," <nowiki>... }+ </nowiki>
External_file ::= External_user_file | External_system_file
External_user_file ::= ' " ' [[#Simple strings|Simple_string]] ' " '
External_system_file ::= <nowiki>"<"</nowiki> [[#Simple strings|Simple_string]] <nowiki>">"</nowiki>
===C externals ===
C_external ::= ' " ' <code>C</code> <nowiki>[</nowiki><code>inline</code>] <nowiki>[</nowiki> [[#External signatures |External_signature]] <nowiki>] [</nowiki> [[#External file use |External_file_use]] <nowiki>] ' " '</nowiki>
===C++ externals ===
C++_external ::= ' " ' <code>C++</code> <code>inline</code> <nowiki>[</nowiki> [[#External signatures |External_signature]] <nowiki>] [</nowiki> [[#External file use |External_file_use]] <nowiki>] ' " '</nowiki>
===DLL externals ===
DLL_external ::= ' " ' <code>dll</code> <nowiki>[</nowiki><code>windows</code><nowiki>] DLL_identifier [DLL_index] [[</nowiki> [[#External signatures |External_signature]] <nowiki>] [</nowiki> [[#External file use |External_file_use]] <nowiki>] ' " ' </nowiki>
DLL_identifier ::= [[#Simple strings|Simple_string]]
DLL_index ::= [[#Integers|Integer]]
===Comments ===
Comment ::= "- -" <nowiki>{</nowiki>[[#Simple strings|Simple_string]] Comment_break ...}*
Comment_break ::= New_line <nowiki>[Blanks_or_tabs] "- -"</nowiki>
===Integers ===
Integer ::= <nowiki>[Integer_base]</nowiki> Digit_sequence
Integer_base ::= "0" Integer_base_letter
Integer_base_letter ::= "b" | "c" | "x" | "B" | "C" | "X"
Digit_sequence ::= Digit+
Digit ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" |
"a" | "b" | "c" | "d" | "e" | "f" |
"A" | "B" | "C" | "D" | "E" | "F" | "_"

View File

@@ -0,0 +1,16 @@
[[Property:title|Quick reference to the Eiffel programming language]]
[[Property:link_title|Language Quick Reference]]
[[Property:weight|4]]
[[Property:uuid|4f61365d-59f6-a394-678b-144bad8ec12f]]
The Quick Reference to the Eiffel programming language provides an informal guide to the syntax and reserved words of the language. The Eiffel programming language is described in detail in the ISO/ECMA standard document, available [http://www.ecma-international.org/publications/standards/Ecma-367.htm online].
Sometimes there are differences between the language as defined by the standard and that which is implemented by Eiffel Software. These differences are documented in the online documentation.
So, the final authority on Eiffel as implemented by Eiffel Software is the content of the standard document, amended by those variances cited in the [[Differences between standard ECMA-367 and Eiffel Software implementation|"differences" chapter of the online documentation]].
This reference is based on the June 2006 ISO/ECMA standard document.

View File

@@ -0,0 +1,88 @@
[[Property:title|Void-safe changes to Eiffel libraries]]
[[Property:weight|0]]
[[Property:uuid|dc993c0e-fbec-dc5a-82c8-fbfd9fa9bc3a]]
==Overview==
During the adoption of void-safety, the software libraries provided by Eiffel Software have been converted to be void-safe. The bulk of the changes made to these libraries will have little or no adverse effect on your existing software as you go through the process of void-safe conversion. However, there are a few changes to the library that we consider "breaking" changes, that is, important changes that might cause problems in existing systems that use certain library classes.
{{note|Many of these changes were in effect in the ''experimental'' mode of versions 6.4 and 6.5. With the release of version 6.6, the ''experimental'' mode of previous versions became the ''default'' mode and, consequently may have caused these changes to become more apparent to some users. A ''compatibility'' mode is available to ease transition. The ''compatibility'' mode is accessible using the <code>-compat</code> command line option or through the EiffelStudio choices provided through the Microsoft Windows ''Start'' button. }}
==Important changes to library classes==
===Class ARRAY===
====New preconditions====
Some additional preconditions are in force in <code>ARRAY</code> in void-safe mode.
In void-unsafe mode, the behavior is equivalent to that of previous versions.
====Feature make_from_special====
The signature of this routine has changed.
Current signature: <code>make_from_special (a: SPECIAL [G])</code>
Previous signature: <code>make_from_special (a: SPECIAL [G]; min_index, max_index: INTEGER)</code>
Using the current version will create an array with a range from 1 to the number of elements in the argument `a`.
====Feature auto_resize====
This implementation (private) feature has been removed.
===Class ARRAYED_LIST===
====Relationship to ARRAY====
Previously <code>ARRAYED_LIST</code> conformed to <code>ARRAY</code>. This is no longer the case. The feature <code>{ARRAYED_LIST}.to_array</code> can be used to produce an instance of <code>ARRAY</code> from an instance of <code>ARRAYED_LIST</code>.
====Features count and area====
Previously these two queries, <code>count</code> and <code>area</code>, were attributes. They are now functions.
===Class HASH_TABLE===
The internal implementation has changed in ways that cause the order of traversal to differ from previous versions.
===Classes SPECIAL and TO_SPECIAL===
====Feature {SPECIAL}.make====
This void-unsafe feature has been removed.
In its place, the creation procedures <code>{SPECIAL}.make_filled</code> and <code>{SPECIAL}.make_empty</code> can be used.
<code>{SPECIAL}.make_filled</code> is available in both ''default'' and ''compatible'' modes. Use this creation procedure if you want code that is compatible with both modes.
<code>{SPECIAL}.make_empty</code> is available in ''default'' mode only.
====Feature {TO_SPECIAL}.make_area====
In order to reflect the above change to class <code>SPECIAL</code>, the <code>make_area</code> feature of <code>TO_SPECIAL</code> has been removed in favor of <code>{TO_SPECIAL}.make_filled_area</code> and <code>{TO_SPECIAL}.make_empty_area</code>.
The availability of <code>{TO_SPECIAL}.make_filled_area</code> and <code>{TO_SPECIAL}.make_empty_area</code> corresponds to that noted above for the creation features of <code>SPECIAL</code>:
<code>{TO_SPECIAL}.make_filled_area</code> is available in both ''default'' and ''compatible'' modes. Use <code>make_filled_area</code> for code that needs to compile in both modes.
<code>{TO_SPECIAL}.make_empty_area</code> is available only in ''default'' mode.
====Relationship of feature {SPECIAL}.count to {SPECIAL}.capacity====
In previous versions, for a particular instance of <code>SPECIAL</code> the queries <code>count</code> and <code>capacity</code> yielded the same value.
This is no longer always true. If an instance of <code>SPECIAL</code> is created with, for example, <code>make_empty (10)</code>, although the <code>capacity</code> will be 10, the <code>count</code> will be zero.
However creating a <code>SPECIAL</code> using <code>make_filled</code> will produce an instance in which <code>count</code> and <code>capacity</code> are equal upon creation. So the behavior is similar to that of previous versions. Also, <code>make_filled</code> is available in both ''default'' and ''compatible'' modes.
If your code depends upon <code>count</code> and <code>capacity</code> having the same value, then you can use <code>make_filled</code> for creation. And then if you need resizing, use the "_with_default" versions of the "resized" features, specifically <code>resized_area_with_default</code> and <code>aliased_resized_area_with_default</code>.

View File

@@ -0,0 +1,335 @@
[[Property:title|Converting existing software to void-safety]]
[[Property:weight|6]]
[[Property:uuid|eb901272-d405-2277-005d-e37275b9baa4]]
If you have been using Eiffel for a while, you may be maintaining systems which were developed before Eiffel became void-safe. If that's the case, then you will probably want to make those systems void-safe.
In this section we will use the experience of converting a set of simple (but not too simple) legacy Eiffel classes to show the types of issues that you may encounter, and how to deal with them.
So in the discussion below, you will see references to these classes:
{| border="1"
|-
! Class name
! Description
|-
| APPLICATION
| Simple root class containing declarations of types NVP and NVP_LIST
|-
| NVP
| Class modeling name/value pairs of type STRING
|-
| NVP_LIST
| Class modeling a list of NVP's with specialized behavior; heir of TWO_WAY_LIST [NVP]
|}
It's not important that you know much about the details of these classes. We will, however, look at certain parts of the classes in enough detail to resolve the conversion issues.
=Conversion considerations=
==To redesign or not to redesign==
During the process of conversion of classes to void-safety, the compiler will point out problems which you will have to fix. Some of these will be straightforward, while others may be tricky. It is natural, or sometimes mandatory, at times to consider changing elements of the design of your software.
Also, as you sift through your existing software during the void-safe conversion, you may not get very far before you see things that you wish had been done differently. This occurs often during reviews of existing systems, not just because of the introduction of void-safety.
In the discussions that follow you will see these redesign opportunities arise, and the decisions that were made for these cases.
==Be aware of changes to Eiffel libraries==
The libraries distributed with EiffelStudio have been converted to support void-safety. Mostly the changes made will cause no problems for existing software. However a few changes have been identified as "breaking" changes. You may or may not encounter the effects of these changes, but you should be aware of how they could effect your software and what options you have for adapting to them. Breaking changes are described in the [[EiffelStudio release notes]] and in the page dedicated to [[Void-safe changes to Eiffel libraries]].
=Conversion process=
==Enable full class checking==
First make sure your project will compile correctly under the configuration of EiffelStudio that you intend to use to convert to void-safe.
Then set the project setting '''Full Class Checking''' to '''True'''. Do a ''[[Clean compile|clean compile]]'' of your system.
Full class checking will analyze your classes to make sure that in cases of inheritance, features of the parent classes are rechecked for validity in the heirs.
Here's an example of the kind of error you might expect when compiling with full class checking:
[[Image:VGCC error]]
The situation here is that the feature <code>split</code> has been inherited (from class <code>TWO_WAY_LIST [G]</code>) by our class <code>NVP_LIST</code>. Feature <code>split</code> includes code to create and attach feature <code>sublist</code> which is typed <code>attached like Current</code> which in this case means <code>attached NVP_LIST</code>. To do this creation, <code>split</code> uses a creation procedure <code>make_sublist</code>.
Now here's the rub: <code>NVP_LIST</code> has not named <code>make_sublist</code> as a creation procedure:
<code>
create
make, make_from_string, make_from_file_named
</code>
If we go to the <code>create</code> part of <code>NVP_LIST</code> and add <code>make_sublist</code> to its list of creation procedures, this will fix the problem:
<code>
create
make, make_from_string, make_from_file_named, make_sublist
</code>
So, fix any problems that arise out of turning on full class checking.
==Enable other project settings==
The second step in conversion of existing software is to change the values of the other void-safe related project settings and use the void-safe configurations for any delivered libraries and precompilations.
In the project settings for the target in which you are working, set '''Void safety''' to '''Complete''', '''Transitional''' , '''Initialization''' or '''Conformance'''.
{{note|Remember that during a transitional period starting with v6.4, there will be multiple versions of the configuration files for Eiffel libraries and precompiles. For example, base.ecf (void-unsafe) and base-safe.ecf (void-safe). Starting with v16.11 there is only one configuration file for libraries (e.g., base.ecf) that works with both void-safe and void-unsafe client software, but if you are using a precompile, there could be different versions for void-safe and void-unsafe precompiles.}}
If necessary, remove Eiffel libraries and any precompiled library that your project uses and re-add them with their void-safe configuration files. Because you've set your target to void-safety, when you click '''Add Library''', you should see only void-safe configurations by default.
You will see a check box on the dialog that you can uncheck if you want to see all available library configurations:
[[Image:VoidSafeAddLibraryDialog]]
Now do a [[Clean compile|clean compile]].
If you've replaced a precompiled library that you have not already built, EiffelStudio will offer to build it for you on the fly:
[[Image:VoidSafePrecompileOffer]]
Now you should see error messages representing any situation in your project in which the compiler determines that it cannot guarantee void-safety.
This is what our legacy system produced:
[[Image:VoidSafeErrorList]]
==Fix the issues==
Next you fix the problems that the compiler discovered. The compiler errors concerning void-safety typically will be of three varieties.
# VEVI: violations of the '''Variable initialization rule'''. An attached variable is not '''properly set'''.
# VUTA: violations of the '''Target rule'''. The target of a feature call is not attached.
# VJAR (and other related codes): violations of attached status considered in conformance. The attachment status of the source of an assignment (or an argument to a feature call) is not compatible with that of the target of the assignment (or the formal argument).
Let's look at some specific cases and how fixing them unfolds.
===Variables not properly set===
[[Image:VoidSafeVEVI1]]
There are two VEVI errors like this in class <code>APPLICATION</code> of our legacy system. They are probably the most obvious and easiest cases to handle.
<code>
feature {NONE} -- Initialization
make
-- Run application.
do
...
end
feature -- Access
my_nvp: NVP
-- NVP for testing
my_nvp_list: NVP_LIST
-- NVP_LIST for testing
</code>
Here attribute declarations for <code>my_nvp</code> and <code>my_nvp_list</code> are made. These are assumed to be attached because of the project setting. But the create routine <code>make</code> fails to create objects and attach them. So by adding those creations, as shown below, the compiler is satisfied.
<code>
make
-- Run application.
do
create my_nvp.make ("SomeName", "SomeValue")
create my_nvp_list.make
...
end
</code>
In a second case, there is also an Initialization rule violation (VEVI), this time on <code>Result</code>, in this routine:
<code>
at_first (nm: STRING): NVP
-- The first found NVP with name matching nm.
-- Or Void if not found
require
nm_valid: nm /= Void and then not nm.is_empty
local
tc: CURSOR
do
tc := cursor
start
name_search (nm)
if not exhausted then
Result := item
end
go_to (tc)
ensure
index_unchanged: index = old index
end
</code>
Here we cannot just ensure that <code>Result</code> is always attached, because, as indicated by the header comment, <code>Result</code> is allowed to be void by design.
So the least impact to this routine will be to declare its type as <code>detachable</code>:
<code>
at_first (nm: STRING): detachable NVP
-- The first found NVP with name matching nm.
-- Or Void if not found
</code>
The same change is made in other routines that can return void by design, particularly including a routine called <code>value_at_first</code>, which gets our attention next.
The case of <code>at_first</code> offered us an opportunity to redesign (or not). We might have been able to leave <code>at_first</code> attached. After all, in void-safe software, the fewer <code>detachable</code>s, the better. Maybe we could devise a way, possibly through preconditions and other queries, that would guarantee that <code>at_first</code> attempts to execute only when it can return a value.
But <code>at_first</code> is an exported query, so a consequence of such a change in the class design is that it would affect the class interface in such a way that existing clients would have to be modified to comply. In other words, it would be a "breaking" change.
===Source of assignment does not conform to target===
The change to <code>at_first</code> satisfies the VEVI issue in <code>at_first</code>, but it introduces a previously unseen conformance issue (VJAR) in the routine <code>value_at_first</code>:
[[Image:VoidSafeVJAR1]]
<code>value_at_first</code> looks like this:
<code>
value_at_first (nm: STRING): detachable STRING
-- Value from first found NVP with name matching nm
-- Or Void of not found
require
nm_valid: nm /= Void and then not nm.is_empty
local
tn: NVP
do
tn := at_first (nm)
if tn /= Void then
Result := tn.value
end
end
</code>
The problem is that the local variable <code>tn</code> is declared as <code>attached</code>, but we know that now the result of <code>at_first</code> is detachable, making this assignment invalid:
<code>
tn := at_first (nm)
</code>
Here the '''attached syntax''' can fix the problem and streamline the routine:
<code>
value_at_first (nm: STRING): detachable STRING
-- Value from first found NVP with name matching nm
-- Or Void of not found
require
nm_valid: nm /= Void and then not nm.is_empty
do
if attached at_first (nm) as tn then
Result := tn.value
end
end
</code>
In this version <code>tn</code> need not be declared as a local variable. Remember that the attached syntax provides a fresh local variable, if the expression is not void.
===Both VEVI and VJAR errors===
A design issue in class <code>NVP_LIST</code> causes both conformance and initialization compiler errors. In the original design, an instance of the class NVP_LIST could traverse its contents NVP-by-NVP with inherited functionality. Additionally, <code>NVP_LIST</code> has immediate functionality allowing an instance to traverse its contents in two different ways returning "sublists" based on recurring patterns of the <code>name</code> attributes of a sequence of name/value pairs.
These two traversal methods are referred to as "sequencing" and "segmenting". It's not important that you understand the details of what these traversals do. But it is important to know that a valid instance of <code>NVP_LIST</code> can either be in the process of sequencing or in the process of segmenting, or neither. It is invalid to be both sequencing ''and'' segmenting.
Two class attributes are maintained to store the recurring patterns of values of <code>{NVP}.name</code> that guide traversal:
<code>
feature {NONE} -- Implementation
sequence_array: ARRAY [STRING]
-- The current array of names being used for
-- sequence traversal
segment_array: ARRAY [STRING]
-- The current array of names being used to determine
-- the termination of list segments
</code>
In the original class design, each of these attributes would be void unless their corresponding traversal was active. So the class contains the following clauses in its invariant:
<code>
not_sequencing_and_segmenting: not (segment_readable and sequence_readable)
sequence_traversal_convention: (sequence_array = Void) = (not sequence_readable)
segment_traversal_convention: (segment_array = Void) = (not segment_readable)
</code>
Of course by default these attributes are considered to be attached. So, because they are not initialized during creation, we see initialization errors. Because elements of the class intentionally set them to <code>Void</code>, we see conformance errors.
Here we have another opportunity to redesign (or not). We could mark the two arrays as <code>detachable</code>, recompile and fix any problems this causes (in fact, it causes eight errors: six Target rule violations, and two conformance issues).
However, because these attributes are not exported, we may be able to leave them attached and make changes to the implementation design without making breaking changes to the interface.
Those exported features which take arguments of the type <code>ARRAY [STRING]</code> which will serve as sequencing or segmenting control also require that the array contain at least one element. For example, the contract for feature <code>segment_start</code> contains these preconditions:
<code>
segment_start (nms: ARRAY [STRING_8])
-- Place segment cursor on the first occurrence of a seqment of list which
-- begins at the current cursor position and
-- terminates in a sequence with names equivalent to and ordered the same as `nms'.
-- If no such sequence exists, then ensure exhausted
require
nms_valid: nms /= Void and then (nms.count > 0)
not_sequencing: not sequence_readable
</code>
Because the restriction always exists that a valid <code>sequence_array</code> or <code>segment_array</code> must contain at least one element, it is possible to redesign the implementation of the class such that an empty <code>sequence_array</code> and <code>segment_array</code> could serve the same purpose as a <code>Void</code> one does in the original design.
So the invariant clauses that we saw above would now become:
<code>
not_sequencing_and_segmenting: not (segment_readable and sequence_readable)
sequence_traversal_convention: (sequence_array.is_empty) = (not sequence_readable)
segment_traversal_convention: (segment_array.is_empty) = (not segment_readable)
</code>
We already have compiler errors (VJAR's) that point us to those places in which we have code that sets either <code>sequence_array</code> or <code>segment_array</code> to <code>Void</code>. Like this:
<code>
segment_array := Void
</code>
These instances need to be changed to attach an empty array, maybe like this:
<code>
create segment_array.make (1, 0)
</code>
Additionally, some postconditions which reference the implementation features <code>sequence_array</code> and/or <code>segment_array</code> would have to be changed. Looking at the postcondition clauses for <code>segment_start</code> we see that <code>segment_array</code> is expected (or not) to be <code>Void</code>:
<code>
ensure
started: (not exhausted) implies (segment_readable and (segment_array /= Void) and (last_segment_element_index > 0))
not_started: exhausted implies ((not segment_readable) and (segment_array = Void) and (last_segment_element_index = 0))
</code>
To support the "empty array" design, <code>segment_start</code>'s postcondition clauses would be:
<code>
ensure
started: (not exhausted) implies (segment_readable and (not segment_array.is_empty) and (last_segment_element_index > 0))
not_started: exhausted implies ((not segment_readable) and (segment_array.is_empty) and (last_segment_element_index = 0))
</code>
{{SeeAlso|<br/>[[Converting EiffelVision 2 Systems to Void-Safety]]<br/>[[Void-safe changes to Eiffel libraries]]}}

View File

@@ -0,0 +1,28 @@
[[Property:title|Mixing void-safe and void-unsafe software]]
[[Property:weight|3]]
[[Property:uuid|3446f214-3c77-ef41-98eb-92942298630c]]
{{underconstruction}}
=Introduction=
Eiffel Software recommends that any new development efforts be implemented using Eiffel's void-safe approach, thus eliminating one more common type of runtime failure. It is also recommended that existing software be converted to void-safety at the earliest opportunity.
Under some circumstances it is possible and even helpful to mix void-safe and void-unsafe libraries. During conversion to void-safety, for example, it can be helpful to compile and test a void-unsafe system with void-safe versions of the libraries it depends upon.
=Rule for mixing void-safety modes=
The rule for using void-safe and void-unsafe software together is fairly simple.
{{Rule|name=Mixing void-safe and void-unsafe software|text=<br/>
1) A class that is void-unsafe may depend upon other classes (as suppliers or ancestors) which are either void-safe or void-unsafe.<br/>
2) A class that is void-safe may depend only upon other classes that are void-safe.}}
This means that if the root class of a system is void-safe, then every other class in the system must also be void-safe.
However, if you are converting a system to void-safety, it's likely that your root class and the classes in the closely related clusters will be void-unsafe. The rule allows you to mix the void-safe versions of the Eiffel Software library classes from the EiffelStudio distribution with your void-unsafe system during conversion.

View File

@@ -0,0 +1,387 @@
[[Property:title|Creating a new void-safe project]]
[[Property:weight|2]]
[[Property:uuid|92cea2e9-b094-6380-2c5d-1cd1eb3038b4]]
{{TOC|limit=2}}
Now that we've been introduced to the Eiffel void-safe facilities, let's look at what it takes to set up a new void-safe software project. Here we'll look at the void-safety related project settings and how the can be used. Then we'll look deeper into the use of some of the void-safe tools.
==Project settings for void-safe projects==
There are two project settings that are related to void-safety. These settings can be set with great granularity throughout your project to allow you maximum flexibility, particularly when including classes or libraries that are void-unsafe or that have been converted to void-safety, but must do double duty in the void-safe and void-unsafe worlds.
===The ''"Void-safe"'' setting===
The '''Void-safe''' setting determines whether and how the Eiffel compiler checks your project against the void-safe related validity rules.
This is the essential void-safe project setting. It can assume one of the following values:
# '''No''': No checking against any of the void-safety validity rules. Attachment marks '''attached''' and '''detachable''' are simply ignored.
# '''Conformance''': The attachment marks are not ignored for type conformance checks (with respect to VJAR/VBAR and related validity rules).
# '''Initialization''': Validity rules are selectively checked. The initialization rule (VEVI) and the target rule (VUTA) are checked only for attached entities and attached call targets -- i.e., detachable cases are not checked.
# '''Transitional''': It is an obsolete level which is for users who have already migrated their code to void-safety using an old version of the compiler which did not implement all the void-safety validity rules (especially with agent initialization).
# '''Complete''': Complete checking against all void-safety validity rules.
So, for a new void-safe project, you would want to set this option first to '''Conformance''', then '''Initialization''' and finally to '''Complete'''. This will let you migrate your code progressively without much changes at each steps.
===The ''"Full class checking"'' setting===
This setting instructs the compiler to recheck inherited features in descendant classes. This setting is True and cannot be changed for projects with some void-safety level enabled.
==Void-safe libraries==
As of EiffelStudio version 13.11, all libraries distributed with EiffelStudio are void-safe except the EiffelCOM library.
{{note|During a period of transition, there are different Eiffel configuration files (.ecf's) for void-unsafe and void-safe projects (for example, base.ecf and base-safe.ecf). If you have set the '''Void-safe''' setting to check for void-safety, then when you add a library to your project in EiffelStudio, you will see only the void-safe configurations by default. Starting with version 16.11 there is only one version of each of the configuration files for each library. The single configuration files serve both void-unsafe and void-safe projects.}}
===Using generic classes===
Void-safety affects generic classes. Fortunately, from the viewpoint of those writing clients to the generic classes in the EiffelBase library, not much has changed. Still, you should understand the interplay between void-safety and [[ET: Genericity and Arrays|genericity]].
Consider a generic class like <code>LIST [G]</code>. The formal generic parameter <code>G</code> represents an arbitrary type. In a generic derivation of <code>LIST [G]</code>, say <code>LIST [STRING]</code>, the formal generic type is replaced by an actual generic type, in this case <code>STRING</code>.
Remember that unconstrained genericity, <code>LIST [G]</code>, for example, is really a case of [[ET: Inheritance#Constrained genericity|constrained genericity]] in which the generic parameter is constrained to <code>ANY</code>, that is, it could be written <code>LIST [G -> ANY]</code>.
With the advent of void-safe Eiffel, the unconstrained generic class name <code>LIST [G]</code> now equates to <code>LIST [G -> detachable ANY]</code>. Because any type, say <code>T</code>, (synonymous with <code>attached T</code> in void-safe Eiffel) conforms to <code>detachable T</code>, this change facilitates the production of generic classes, but has little effect on writers of clients to those classes.
This change works for all the generic classes in EiffelBase ... except for one: <code>ARRAY</code>. Arrays are a special case because we often create arrays with a pre-allocated number of elements. In the case of expanded types, there's not a problem. For example, in this code
<code>
my_array: ARRAY [INTEGER]
...
create my_array.make (1, 100)
</code>
we create <code>my_array</code> with one hundred <code>INTEGER</code> elements. <code>INTEGER</code> is an expanded type, and each element is initialized by applying the default initialization rule for <code>INTEGER</code>, i.e, the integer representation of zero.
However, if <code>my_array</code> had been declared of a type with reference semantics, say <code>STRING</code> (meaning, of course, <code>attached STRING</code>, the default rule would not work well, because the default initialization for references types is <code>Void</code> which would not be allowed in an array of elements of any attached type.
The solution to this challenge is fairly simple. For arrays of elements of detachable or expanded types, there is no different behavior. When dealing with arrays of elements of attached types, we must be careful.
Creating an array using <code>ARRAY</code>'s creation procedure <code>make</code> may still be safe in some cases. Specifically, <code>make</code> can be used with arrays of elements of attached types if the arguments have values such that an empty array will be created, that is, when
<code>
min_index = max_index + 1
</code>
In all other situations involving arrays of elements of attached types, <code>make</code> may not be used to do the creation. Rather, you should use the creation procedure <code>make_filled</code> which takes three arguments. The first is an object of the type of the array, and the second and third are the minimum and maximum indexes, respectively. When the array is created, each of the elements will be initialized with a reference to the object of the first argument.
So, a call using <code>make_filled</code> would look like this:
<code>
my_array: ARRAY [STRING]
...
create my_array.make_filled (" ", 1, 100)
</code>
Upon creation, each element of the array will reference the same object; an object of type <code>STRING</code> composed of one space character.
==Using the ''attribute'' keyword carefully==
The keyword <code>attribute</code> should be used with some care. You might be tempted to think that it would be convenient or add an extra element of safety to use [[Void-safety: Background, definition, and tools#Self-initializing attributes|self-initializing attributes]] widely. And in a way, you would be correct. But you should also understand that there is a price to pay for using self-initializing attributes and stable attributes. It is that upon every access, an evaluation of the state of the attribute must be made. So, as a general rule, you should avoid using self-initializing attributes only for the purpose of lazy initialization.
==More about the ''attached syntax''==
The complete attached syntax is:
<code>
attached {SOME_TYPE} exp as l_exp
</code>
In this section, we will see more ways in which to use this versatile language facility.
===As a CAP-like construct which yields a local variable===
In the introduction to the attached syntax, we used an example which showed how the attached syntax is directly relevant to void-safety. That is, the code:
<code>
if x /= Void then
-- ... Any other instructions here that do not assign to x
x.f (a)
end
</code>
is a CAP for <code>x</code> ... but that's only true if <code>x</code> is a local variable or a formal argument to the routine that contains the code.
So to access a detachable attribute safely, we could declare a local variable, make an assignment, and test for <code>Void</code> as above. Something like this:
<code>
my_detachable_attribute: detachable MY_TYPE
...
some_routine
local
x: like my_detachable_attribute
do
x := my_detachable_attribute
if x /= Void then
-- ... Any other instructions here that do not assign to x
x.f (a)
end
...
</code>
The attached syntax can both check the attached status of a detachable attribute and also provide a new local variable. So the routine becomes:
<code>
some_routine
do
if attached my_detachable_attribute as x then
-- ... Any other instructions here that do not assign to x
x.f (a)
end
...
</code>
===As a test for attachment===
In its simplest form, the attached syntax can be used to test attached status only:
<code>
if attached x then
do_something
else
do_something_different
end
</code>
So in this simple form, <code>attached x</code> can be used instead of <code>x /= Void</code>. The two are semantically equivalent, and which one you choose is a matter of personal preference.
===As a tool for "once per object"===
There is a code pattern for functions that exists in some Eiffel software to effect "once-per-object / lazy evaluation".
{{note|As of EiffelStudio version 6.6, the use of this code pattern effecting "once per object" is no longer necessary. V6.6 includes explicit support for <code>once</code> routines which can be adjusted by a [[ET: Once routines and shared objects#Adjusting once semantics with "once keys"|once key]] to specify once per object.}}
This "once-per-object" code pattern employs a cached value for some object which is not exported. When it is applied, the "once-per-object" function checks the attachment status of the cached value. If the cached value is void, then it is created and assigned to <code>Result</code>. If the cached value was found already to exist, then it is just assigned to <code>Result</code>.
Here's an example of this pattern used to produce some descriptive text of an instance of its class:
<code>
feature -- Access
descriptive_text: STRING
local
l_result: like descriptive_text_cache
do
l_result := descriptive_text_cache
if l_result = Void then
create Result.make_empty
-- ... Build Result with appropriate
-- descriptive text for Current.
descriptive_text_cache := Result
else
Result := l_result
end
ensure
result_attached: Result /= Void
result_not_empty: not Result.is_empty
result_consistent: Result = descriptive_text
end
feature {NONE} -- Implementation
descriptive_text_cache: like descriptive_text
</code>
This example will not compile in a void-safe project (class types are attached by default). The problem is that the attribute <code>descriptive_text_cache</code> is of an attached type, therefore will be flagged by the compiler as not properly set (VEVI). Of course, it will be ... that's the whole idea here: not to initialize <code>descriptive_text_cache</code> until it's actually used. So it sounds like <code>descriptive_text_cache</code> should be declared detachable. That is:
<code>
descriptive_text_cache: detachable like descriptive_text
</code>
This change will make this routine compile in a void-safe project. But you should notice that there is a ripple-down effect due to the change. Within the routine, <code>l_result</code> is typed <code>like descriptive_text_cache</code>, so it also will be detachable. Therefore we might expect trouble, because later in the routine we have:
<code>
Result := l_result
</code>
Because we know Result is attached and l_result is detachable, we might expect a compiler error in which the source of an assignment does not conform to its target (VJAR).
But we don't get such an error. The reason is two-fold. First, <code>l_result</code> is a local variable whose use can be protected by a CAP. Second, the CAP in this case is the check to ensure that <code>l_result</code> is not void. We only make the assignment to <code>Result</code> if <code>l_result</code> is not void. So the compiler can prove that <code>l_result</code> cannot be void at the point at which the assignment occurs ... therefore, no error.
Because the '''attached syntax''' can test attached status and provide a local variable, it can be used to remove some unnecessary code from this routine. The version of the routine that follows shows the attached syntax being used to test the attached status of <code>descriptive_text_cache</code> and yield the local variable <code>l_result</code> in the case that <code>descriptive_text_cache</code> is indeed attached.
<code>
descriptive_text: STRING
do
if attached descriptive_text_cache as l_result then
Result := l_result
else
create Result.make_empty
-- ... Build Result with appropriate
-- descriptive text for Current.
descriptive_text_cache := Result
end
ensure
result_attached: Result /= Void
result_not_empty: not Result.is_empty
result_consistent: Result = descriptive_text
end
feature {NONE} -- Implementation
descriptive_text_cache: like descriptive_text
</code>
===As a replacement for assignment attempt===
The assignment attempt ( <code>?=</code> ) has traditionally been used to deal with external objects (e.g., persistent objects from files and databases) and to narrow the type of an object in order to use more specific features. The latter is a process known by names such as "down casting" in some technological circles. A classic example is doing specific processing on some elements of a polymorphic data structure. Let's look at an example. Suppose we have a <code>LIST</code> of items of type <code>POLYGON</code>:
<code>
my_polygons: LIST [POLYGON]
</code>
<code>POLYGON</code>s could be of many specific types, and one of those could be <code>RECTANGLE</code>. Suppose too that we want to print the measurements of the diagonals of all the <code>RECTANGLE</code>s in the list. Class <code>RECTANGLE</code> might have a query <code>diagonal</code> returning such a measurement, but <code>POLYGON</code> would not, for the reason that the concept of diagonal is not meaningful for all <code>POLYGON</code>s, e.g., <code>TRIANGLE</code>s.
As we traverse the list we would use assignment attempt to try to attach each <code>POLYGON</code> to a variable typed as <code>RECTANGLE</code>. If successful, we can print the result of the application of <code>diagonal</code>.
<code>
l_my_rectangle: RECTANGLE
...
from
my_polygons.start
until
my_polygons.exhausted
loop
l_my_rectangle ?= my_polygons.item
if l_my_rectangle /= Void then
print (l_my_rectangle.diagonal)
print ("%N")
end
my_polygons.forth
end
</code>
The '''attached syntax''' allows us to check both attached status and type, and provides us with a fresh local variable when appropriate:
<code>
from
my_polygons.start
until
my_polygons.exhausted
loop
if attached {RECTANGLE} my_polygons.item as l_my_rectangle then
print (l_my_rectangle.diagonal)
print ("%N")
end
my_polygons.forth
end
</code>
As with the other examples of the '''attached syntax''', it is no longer necessary to make a declaration for the local variable, in this case <code>l_my_rectangle</code>.
==More about CAPs==
===Use of <code>check</code> instructions===
In void-safe mode, the compiler will accept code that it can prove will only apply features to attached references at runtime ... and you help this process along by using the tools of void-safety, like attached types and CAPs. On the other hand, the compiler will reject code that it cannot guarantee is void-safe. Sometimes this may cause you a problem. There may be subtle situations in which you feel quite certain that a section of code will be free of void calls at runtime, but the compiler doesn't see it the same way, and rejects your code. In cases like this, you can usually satisfy the compiler by using <code>check</code> instructions.
Technically speaking, <code>check</code> instructions are not CAPs. But they are useful in cases in which an entity is always expected to be attached at a certain point in the code. In the following example, the attribute <code>my_detachable_any</code> is detachable. But at the particular point at which it is the source of the assignment to <code>l_result</code>, it is expected always to be attached. If it is not attached at the time of the assignment, and therefore <code>l_result</code> becomes void, then an exception should occur. The <code>check</code> instruction provides this behavior.
The following sample shows the <code>check</code> instruction at work. There are reasons why this is not the best use use of <code>check</code> in this case, and we will discuss that next.
<code>
-- A not-so-good example of using check.
my_detachable_any: detachable ANY
...
my_attached_any: ANY
local
l_result: like my_detachable_any
do
l_result := my_detachable_any
check
attached l_result
end
Result := l_result
end
</code>
Here the assertion in the <code>check</code> guarantees that <code>l_result</code> is attached at the time of its assignment to <code>Result</code>. If <code>my_detachable_any</code> is ever not attached to an object, then an exception will be raised.
So what's wrong with the sample above? It would be fine in ''workbench'' code, but what happens if the code is in ''finalized'' mode, in which assertions are typically discarded?
The answer is that the <code>check</code> in the sample above would no longer be effective, and the resulting executable would no longer be void-safe.
The solution to this problem is found in a different form of the <code>check</code> instruction. Consider the same example, but this time using <code>check ... then ... end</code>:
<code>
-- A better way of using check.
my_detachable_any: detachable ANY
...
my_attached_any: ANY
do
check attached my_detachable_any as l_result then
Result := l_result
end
end
</code>
Here, in the improved version of the example, the <code>check ... then ... end</code> is used along with the <code>attached</code> syntax. This streamlines the code a bit by eliminating the need to declare a separate local entity, while achieving the same effect as the previous example. If <code>my_detachable_any</code> is attached at runtime, then the temporary variable <code>l_result</code> is created and attached to the same object. Then the body of the <code>check ... then ... end</code> is executed. If <code>my_detachable_any</code> is not attached, an exception occurs.
Another important benefit, one that solves the problem with the original example, comes from the way in which <code>check ... then ... end</code> is handled by the compiler. The <code>check ... then ... end</code> form '''is always monitored, even if assertion checking is turned off at all levels''', as is usually done in finalized code.
===Choosing CAPs versus the Attached Syntax===
The attached syntax is convenient because it can check attached status and deliver a new local variable at the same time. But there are cases in which you might choose instead to define a local variable and use a CAP. Suppose you had code acting on several similar and detachable expressions, and you use the attached syntax in each case:
<code>
foobar
do
if attached dictionary_entry ("abc") as l_abc then
l_abc.do_something
end
if attached dictionary_entry ("def") as l_def then
l_def.do_something
end
if attached dictionary_entry ("ghi") as l_ghi then
l_ghi.do_something
end
end
</code>
This routine causes three local variables to be allocated for the duration of routine <code>foobar</code>, one each for <code>l_abc</code>, <code>l_def</code>, and <code>l_ghi</code>. And it is no better to do this:
<code>
foobar
do
if attached dictionary_entry ("abc") as l_entry then
l_entry.do_something
end
if attached dictionary_entry ("def") as l_entry then
l_entry.do_something
end
if attached dictionary_entry ("ghi") as l_entry then
l_entry.do_something
end
end
</code>
Even though the names are the same, still three separate local variables are allocated for <code>foobar</code>.
In cases like this, you could effect a minor performance improvement by declaring one local variable and reusing it. In the following code, only one local variable is used and access to it is protected by the CAP <code>if l_entry /= Void then</code>.
<code>
foobar
local
l_entry: like dictionary_entry
do
l_entry := dictionary_entry ("abc")
if l_entry /= Void then
l_entry.do_something
end
l_entry := dictionary_entry ("def")
if l_entry /= Void then
l_entry.do_something
end
l_entry := dictionary_entry ("ghi")
if l_entry /= Void then
l_entry.do_something
end
end
</code>
==Stable attributes==
Remember that stable attributes are actually detachable attributes, with the difference that they can never be the target of an assignment in which the source is <code>Void</code> or anything that could have a value of <code>Void</code>.
Stable attributes are useful in situations in which there are valid object life scenarios in which some particular attribute will never need an object attached, or will only need an object attached late in the scenario. So in this case, the attribute is used only under certain runtime conditions. Declaring these attributes as stable eliminates the need to make attachments during object creation. Yet once needed, that is, once the attribute is attached, it will always be attached.
Also, you should remember that unlike other attributes, you can access stable attributes directly in a CAP:
<code>
my_stable_attribute: detachable SOME_TYPE
note
option: stable
attribute
end
...
if my_stable_attribute /= Void then
my_stable_attribute.do_something
end
...
</code>
{{SeeAlso| [[Void-safety: Background, definition, and tools#Types as "attached" or "detachable"|Types as "attached" or "detachable"]].}}

View File

@@ -0,0 +1,22 @@
[[Property:title|Void-safe programming in Eiffel]]
[[Property:weight|10]]
[[Property:uuid|a03568e8-eb79-70d7-04a3-6fd3ed7ac2b3]]
=Void-safe software development using Eiffel: introduction=
When you develop software in Eiffel, you can be assured (at compile time) that your system will not attempt (at run time) to apply a feature to a void reference -- or, in the terminology of other languages such as C, "dereference a null pointer".
Throughout the history of Eiffel, new capabilities -- agents, the SCOOP concurrency mechanism and many others -- have added considerable expressive power to the languag,e while causing minimum impact on existing software. Void-safe Eiffel is such an innovation, which instead of adding new mechanisms ''removes'' a major source of instability in programs, present in all other major languages: null-pointer dereferencing. To say that Eiffel is void-safe means that such catastrophic yet common errors simply will not occur.
There is in fact no need to speak of "void-safe Eiffel". The language is just Eiffel... and it is void-safe, just as it is statically typed. We still occasionally refer to "Void-safe Eiffel" simply because until 2005 or so Eiffel was not void-safe (it had to start somewhere), and you may still encounter older documentation that talks about "calls on void targets" (null-pointer dereferences). But in today's Eiffel such an event is impossible.
The rest of this chapter explains void safety:
# How is void-safety defined?
# What are the specific elements of the mechanism?
# How do these relate to Eiffel before void-safety?
# What do I need to know to produce standard Eiffel software?
# What do I need to know to convert my existing systems to be standard?

View File

@@ -0,0 +1,290 @@
[[Property:title|Void-safety: Background, definition, and tools]]
[[Property:weight|0]]
[[Property:uuid|689f62b2-5675-5ab6-cd47-d891cf3d484d]]
=Background=
The primary focus of Eiffel is on software quality. Void-safety, like static typing, is another facility for improving software quality. Void-safe software is protected from run time errors caused by calls to void references, and therefore will be more reliable than software in which calls to void targets can occur. The analogy to static typing is a useful one. In fact, void-safe capability could be seen as an extension to the type system, or a step beyond static typing, because the mechanism for ensuring void-safety is integrated into the type system.
==Static typing==
You know that static typing eliminates a whole class of software failures. This is done by making an assurance at compile time about a feature call of the form:
<code>
x.f (a)
</code>
Such a feature call is judged acceptable at compile time only if the type of <code>x</code> has a feature <code>f</code> and that any arguments, represented here by <code>a</code>, number the same as the formal arguments of <code>f</code>, and are compatible with the types of those formal arguments.
In statically typed languages like Eiffel, the compiler guarantees that you cannot, at run time, have a situation in which feature <code>f</code> is not applicable to the object attached to <code>x</code>. If you've ever been a Smalltalk programmer, you are certainly familiar with this most common of errors that manifests itself as "Message not understood." It happens because Smalltalk is not statically typed.
==Void-unsafe software==
Static typing will ensure that there is some feature <code>f</code> that can be applied at run time to <code>x</code> in the example above. But it does not assure us that, in the case in which <code>x</code> is a reference, that there will always be an object attached to <code>x</code> at any time <code>x.f (a)</code> is executed.
This problem is not unique to Eiffel. Other environments that allow or mandate reference semantics also allow the possibility of void-unsafe run time errors. If you've worked in Java or .NET you may have seen the NullReferenceException. Sometimes you might have experienced this rather poetic sounding message: "Object reference not set to an instance of an object". In Eiffel you would see "Feature call on void target". All these are the hallmarks of run time errors resulting from void-unsafe software.
{{note|If you need a review of difference between reference types and expanded types in Eiffel, see [[ET: The Dynamic Structure: Execution Model|the chapter of the Eiffel Tutorial dedicated to the Eiffel execution model]]. }}
Of course this is not an issue with instances of expanded types, because these instances are indeed "expanded" within their parent objects. But we could not imagine a world with expanded types only. References are important for performance reasons and for modeling purposes. For example, consider that a car has an engine and a manufacturer. When we model cars in software, it might be appropriate for engines to be expanded types, as each car has one engine. But certainly the same is not true for manufacturer. Many cars can share, through a reference, a single manufacturer.
So, references are necessary, but we want them to be trouble free.
==Void-safe software==
Void-safe software, then, is software in which the compiler can give assurance, through a static analysis of the code, that at run time whenever a feature is applied to a reference, that the reference in question will have an object attached. This means that the feature call
<code>
x.f (a)
</code>
is valid only if we are assured that <code>x</code> will be attached to an object when the call executes.
{{info|This validity rule is called the '''Target rule''', validity code VUTA, and is the primary rule for void-safety. In the following discussion, you will see that other validity rules are involved, too. You can see the formal definition of all validity rules in the [http://www.ecma-international.org/publications/standards/Ecma-367.htm ISO/ECMA standard document] available online. }}
Once we have committed ourselves to this validity rule, we must have a strategy for complying with the rule.
=Elements of the void-safe strategy=
Here are the tools of void-safe trade. They will each be addressed in more detail throughout the documentation that follows. As you look at these elements it helps to try to think about things from the compiler's viewpoint ... after all, it is the compiler that we expect to give us the guarantee that our code is indeed void-safe.
First let's look at a couple of approaches that won't work.
It might occur to us that we could enforce compliance with the target rule by simply eliminating the concept of void references. But this would not be practical. Void is a valuable abstraction that is useful in many situations, such as providing void links in structures. So, we must keep void ... but we want to keep it under control.
Another thought might be that we could just have the compiler do all the work for us. But would be impossibly time consuming for the compiler to investigate every conceivable execution path available to a system to make certain that every possible feature call was made on an attached reference.
So, all of this boils down to the fact that we have to take some actions that help the compiler along. That's what the following are about.
===Certified Attachment Patterns (CAPs)===
We know that in the context of certain code patterns, it is clear that it would be impossible for a reference to be void. These patterns are identified and we call them CAPs, short for Certified Attachment Patterns. Here is a very straightforward example expressed in a syntax that should be familiar to all Eiffel developers:
<code>
if x /= Void then
-- ... Any other instructions here that do not assign to x
x.f (a)
end
</code>
Here a check is made to ensure <code>x</code> is not void. Then as long as no assignments to <code>x</code> are made in the interim, a feature <code>f</code> can be applied to <code>x</code> with the certainty that <code>x</code> will be attached at the time ... and importantly, this can be determined at compile time. So, we say that this code pattern is a CAP for <code>x</code>.
It is important to understand that in this example (and with other CAPs), <code>x</code> is allowed to be a local variable or formal argument only. That is, <code>x</code> may not be an attribute or general expression (with one exception which we will see [[#Stable attributes|below]]). Direct access to class attribute references cannot be allowed via a CAP due to the fact that they could be set to void by a routine call in some execution path invoked by the intervening instructions or possibly even different process thread. In a later [[Void-safety: Background, definition, and tools#Types as "attached" or "detachable"|section]], we well see that this is not quite such a limitations as it may appear at this point.
{{note|You will find more useful information about CAPs in [[Creating a new void-safe project#More about CAPs|More about CAPs]]. Learn how certain code patterns are determined to be CAPs in [[What makes a Certified Attachment Pattern]]. }}
===The ''attached syntax'' (object test)===
For the purposes of void-safety, the '''attached syntax''' does double duty for us. It allows us to make certain that a reference is attached, and it provides us a safe way to access objects that are attached to class attributes.
We noted earlier that this code
<code>
if x /= Void then
-- ... Any other instructions here that do not assign to x
x.f (a)
end
</code>
creates a CAP for feature calls on <code>x</code>, but only if <code>x</code> is a local variable or a formal argument.
By using the '''attached syntax''', we can perform an '''object test''' on a variable. That is, the attached syntax is a <code>BOOLEAN</code> expression which provides an answer to the question "Is <code>x</code> attached to an object?" At the same time, if indeed <code>x</code> is attached to an object, the attached syntax will deliver to us a fresh local variable, also attached to <code>x</code>'s object, on which we can make feature calls.
<code>
if attached x as l_x then
l_x.f (a)
end
</code>
In the example above, <code>x</code> is tested to make certain that it is attached. If so, the new local <code>l_x</code> becomes attached to the same object as <code>x</code>. And so the object can be used safely even if <code>x</code> is a class attribute. So, the attached syntax, is really another CAP, because it provides a clearly verifiable place for the application of features to targets that are guaranteed not to be void.
{{note|The attached syntax has other syntax variations as well as other uses. These will be discussed [[Creating a new void-safe project#More about the attached syntax|later]]. }}
One way to make sure we comply with the target rule would be always use a CAP or the attached syntax every time we want to apply a feature to a referenced object. That might work, but it falls among the impractical approaches to the problem ... it would break a very high percentage of existing Eiffel code, not to mention cluttering things up quite a bit.
===Types as "attached" or "detachable"===
Rather than trying to protect every feature call, Eiffel allows us to declare any variable as being of an '''attached type'''. This is an important extension to the Eiffel type system.
In Eiffel prior to the introduction of void-safe facilities, any reference variable could be set to <code>Void</code>. So, all variables were considered '"detachable"'.
The current standard Eiffel supports a mixture of '''attached''' and '''detachable''' types. When a variable is declared of an attached type, as in the following example, then the compiler will prevent it from being set to <code>Void</code> or set to anything that can be set to <code>Void</code>.
<code>
my_attached_string: attached STRING
</code>
It is easy to imagine that the more declarations are of attached types, the easier it will be to guarantee that a call to a void target cannot take place at run time. In fact, if every declaration was guaranteed to be of an attached type, then that would be all that was needed to satisfy the Target rule.
However, it wouldn't be workable to have only attached types, because sometimes it's important to allow references to have a value of <code>Void</code>.
When it is necessary to allow <code>Void</code> as a value, a declaration can use the ''detachable mark'' as in the following.
<code>
my_detachable_string: detachable STRING
</code>
This doesn't mean that on every declaration you must put either an ''attached mark'' or a ''detachable mark''. Declarations that are unmarked are allowed. If a declaration contains neither '''attached''' nor '''detachable''', then it is assumed to be '''attached'''.
In Eiffel then, all declarations will have types that are either '''attached''' or '''detachable'''. As a result, we need only use CAPs and the attached syntax with detachable types. So the important thing to remember is that ''direct access to class attributes of detachable types is never void-safe.''
====Attachment and conformance====
The distinction between attached and detachable types results in a small but important addition to the rules of conformance. Because variables declared as attached types can never be void, then it is important not to allow any assignment of a detachable source to an attached target. However, assigning an attached source to a detachable target is permissible. The following code shows both cases (as described earlier, class types are attached by default).
<code>
my_attached_string: STRING
my_detachable_string: detachable STRING
...
my_attached_string := my_detachable_string -- Invalid
my_detachable_string := my_attached_string -- Valid
</code>
===Initialization rule===
If we have attached types, then we can assume variables declared of these types, once attached, will always be attached. But how do they get attached in the first place? That's what the initialization rule is all about.
The rule says that at any place in which a variable is accessed, it must be '''properly set'''. A variable's being properly set has a precise, but not particularly simple definition in the Eiffel standard.
{{info|You can find the formal definition of the '''Variable initialization rule''', validity code VEVI, and its related concepts such as '''properly set''' variables in the [http://www.ecma-international.org/publications/standards/Ecma-367.htm ISO/ECMA standard document]. }}
Still, it's not too hard to understand the basics of initializing variables of attached types:
* For the initialization of attributes of a class, we can apply a rule similar to that of the initial evaluation of class invariants ... that is, everything must be in order upon completion of a creation procedure. If a class attribute is of an attached type, then each of the class's creation procedures is responsible for making sure that the attribute is attached to an object upon its completion.
* A local variable is considered properly set if it is initialized at some point '''preceding''' its use in any execution path in which it is used. So immediately after its <code>create</code> instruction, the local variable would be considered properly set. But if the <code>create</code> occurred in the <code>then</code> part of an <code>if</code> instruction, the local variable would not be properly set in the <code>else</code> part of that same <code>if</code> instruction:
<code>
my_routine
-- Illustrate properly set local variable
local
l_my_string: STRING
do
if my_condition then
create l_my_string.make_empty
-- ... l_my_string is properly set here
else
-- ... l_my_string is not properly set here
end
end
</code>
* A variable is considered properly set if it is '''self-initializing'''. What it means to be self-initializing is explained below.
===Self-initializing attributes===
A self-initializing attribute is guaranteed to have a value when accessed at run time. Declarations of self-initializing attributes are characterized by the use of the code that follows the <code>attribute</code> keyword. The code is executed to initialize the attribute in the case that the attribute is accessed prior to being initialized in any other way.
So, self-initializing attributes are ordinary attributes, with the restriction that they are of both ''attached'' types and ''reference'' types (i.e., not expanded types or constants). Self-initializing attributes still can be, and typically will be initialized in the traditional ways. The difference is that the code in the attribute part serves as a kind of safety net guaranteeing that a self-initializing attribute will never be void, even if it is accessed prior to being initialized by one of the traditional means.
<code>
value: STRING
attribute
create Result.make_empty
end
</code>
In the example above, the attribute <code>value</code> will be attached to an object of type <code>STRING</code>, in fact, the empty string, if no other initialization occurs before the first access of <code>value</code>.
===Rule for conformance===
You will remember that the Eiffel type system dictates that an assignment instruction:
<code>
x := y
</code>
is valid only if the type of <code>y</code> is '''compatible''' with the type of <code>x</code>. Compatibility, in turn, means either '''conversion''' or '''conformance'''.
The fact that all types are either '''attached''' or '''detachable''' adds another dimension to rule for conformance:
*If x is of an attached type, then y must be of an attached type.
This prevents us from circumventing attached status at run time. If <code>x</code> is of a detachable type, then <code>y</code> could be either a detachable or attached type.
The same goes for routine calls. In a call:
<code>
z.r (y)
</code>
where <code>x</code> is the formal argument for <code>r</code>, then if x is of an attached type, then y must be of an attached type.
===Stable attributes===
Stable attributes are really stable ''detachable'' attributes, as adding the concept of stability is meaningful only for detachable attributes. Declaring a detachable attribute as stable, means that it behaves like a detachable attribute except that its assignment rules mimic those of attached attributes. In other words, a stable attribute does not need to be attached during object creation the way that attributes declared as attached must. But like attached type attributes, stable attributes can never be the target of an assignment in which the source is <code>Void</code> or a detachable type.
<code>
my_test: detachable TEST
note
option: stable
attribute
end
</code>
This means that even though stable attributes do not need to be initialized like attributes of attached types, once they are attached to an object, they can never be void again.
Stable attributes are also interesting in that they are the only exception to the rule given above in the [[Void-safety: Background, definition, and tools#Certified Attachment Patterns (CAPs)|CAPs section]] that stated that direct access to attributes cannot be protected by a CAP. A stable attribute can be used under the protection of a CAP. This is because once a stable attribute has an object attached, it can never again be set to <code>Void</code>. So there's no worry about having the attribute's state going unexpectedly from attached to non-attached because of the actions of other routines or threads.
===Rule for generic parameters===
Generic classes provide another question. A generic class like
<code>
class
C [G]
...
</code>
allows us to create a type by providing a specific actual generic parameter for the formal parameter <code>G</code>.
So, two valid derivations are:
<code>
my_integer_derivation: C [INTEGER]
</code>
and
<code>
my_employee_derivation: C [EMPLOYEE]
</code>
If class C contains a declaration:
<code>
x: G
</code>
What do we know about the void-safety of <code>x</code> ?
In the case of the <code>INTEGER</code> derivation above, we know <code>x</code> is safe because <code>INTEGER</code> is an expanded type. But often types like <code>EMPLOYEE</code> will be reference types which could be void at run time.
'''For a class like <code>C [G]</code>, <code>G</code> is considered detachable'''. As a result, because of the [[Void-safety: Background, definition, and tools#Rule for conformance|rule for conformance]], any class will work for an actual generic parameter. That means that both of the following are valid generic derivations:
<code>
my_detachable_string_derivation: C [detachable STRING]
my_attached_string_derivation: C [attached STRING]
</code>
If <code>C</code> contains a declaration <code>x: G</code>, the application of features to <code>x</code> must include verification of attachment (CAPs, attached syntax, etc).
Constrained genericity can be used to create generic classes in which the generic parameter represents an attached type. If class <code>C</code> had been defined as:
<code>
class C [G -> attached ANY]
...
</code>
then <code>x</code> in this class <code>G</code> represents an attached type. Consequently, the actual generic type in any derivation must be attached ... and feature calls on <code>x</code> are safe.
===Rule for ARRAYs===
The rule for generic parameters applies to all generic types ... except <code>ARRAYs</code>. In the typical creation of an <code>ARRAY</code>, we would provide a minimum and maximum index.
<code>
my_array: ARRAY [STRING]
...
create my_array.make (1, 100)
</code>
During creation, an area to store the appropriate number of entries is also created. And depending upon the actual generic parameter, these entries are either objects for expanded types or references for reference types.
In the case of an actual generic parameter of an attached reference type, all the elements must be attached to instances of type during the creation of the ARRAY. The <code>make</code> procedure would not do this. Creation of an <code>ARRAY</code> in which the actual generic parameter is attached must be done using the <code>make_filled</code> creation procedure.
<code>
create my_array.make_filled ("", 1, 100)
</code>
The first argument is an object of the actual generic type, in this case an empty <code>STRING</code>. Every entry in the newly created <code>ARRAY</code> will be initialized to reference this object.
For more detail on void-safe use of arrays and other generic classes, see the section: [[Creating a new void-safe project#Using generic classes|Using generic classes]].

View File

@@ -0,0 +1,182 @@
[[Property:title|What makes a Certified Attachment Pattern]]
[[Property:weight|8]]
[[Property:uuid|1a20197d-5a88-59c3-9a04-512399125661]]
==A little background on CAPs==
Certified Attachment Patterns (CAPs) were described in the section on [[Void-safety: Background, definition, and tools#Certified attachment patterns (CAPs)|void-safety tools]]. To review, a CAP is a code pattern for a certain expression, say <code>exp</code> of a detachable type that ensures that <code>exp</code> will never have a void run-time value within the covered scope.
A simple example is the familiar test for void reference:
<code>
if l_x /= Void then
l_x.do_something -- Valid for formal arguments, local variables, and stable attributes
end
</code>
We know that after the explicit check to make sure <code>l_x</code> is not <code>Void</code>, that the feature application <code>l_x.do_something</code> is void-safe.
Of course, you should remember from previous discussions that <code>l_x</code> must be a local variable, a formal argument, or a [[Void-safety: Background, definition, and tools#Stable attributes|stable attribute]].
When void-safety was first envisioned for Eiffel, it was intended that individual CAPs would be proven or certified and documented. This would produce a "catalog" of CAPs.
What happened instead is that the members of the Eiffel standard committee have been able to produce and publish as part of the [http://www.ecma-international.org/publications/standards/Ecma-367.htm standard] a definition of the nature of a CAP from which a determination can be made as to whether a particular code pattern is or is not a CAP.
The definition in the standard document is not easily readable by most developers. So, in this documentation, you will see various examples of CAPs and the rationale behind them.
==The standard CAP definition==
The Eiffel standard (2nd edition, June 2006) defines a CAP as follows:
----
'''''A Certified Attachment Pattern (or CAP) for an expression <code>exp</code> whose type is detachable is an occurrence of <code>exp</code> in one of the following contexts: '''''
'''''1. <code>exp</code> is an Object-Test Local and the occurrence is in its scope. '''''
'''''2. <code>exp</code> is a read-only entity and the occurrence is in the scope of a void test involving <code>exp</code>.'''''
----
The terminology used in the definition is precise. For example, terms like "read-only entity" and "scope of a void test" have specific meanings that are supported by their own definitions in the standard.
Still, the standard does contain informative text that gives us a guideline that a CAP is a scheme to ensure that a particular expression of a detachable type will never have void run-time value in the scope covered by the CAP.
The discussion here will follow that guideline, and, as such, will be less formal (and consequently less precise) than that in the standard, and is intended to be a practical guide. Of course, the [http://www.ecma-international.org/publications/standards/Ecma-367.htm standard document] is available for download if you wish to investigate the specifics.
==CAP-able expressions==
In the first context in the definition above, the expression <code>exp</code> can be an '''Object-Test Local'''. An Object-Test Local is the identifier specified for a fresh local entity in an '''object test'''. Remember, object tests are coded using the [[Void-safety: Background, definition, and tools#The attached syntax (object test)|attached syntax]].
<code>
attached x as l_x
</code>
In the object test expression above, the identifier '''<code>l_x</code>''' is an Object-Test Local.
In the second context, the expression can be a '''read-only entity'''. Read-only entities are:
# Constant attributes
# Formal arguments
# Object-Test Locals
# <code>Current</code>
Additionally, the Eiffel Software compiler allows for [[Void-safety: Background, definition, and tools#Stable attributes|stable attributes]] and local variables to be protected by a CAP.
===Stable attributes===
Stable attributes are the only class attributes which are CAP-able. This is because stable attributes, once attached at run-time, can never have a void value again. So, you use stable attributes safely by using them under the protection of a CAP. Consider this stable attribute:
<code>
my_stable_string: detachable STRING
note
option: stable
attribute
end
</code>
The detachable attribute <code>my_stable_string</code>, because it is stable, is not required to be initialized during the creation of instances of the class in which it is a feature. That means that for each instance, <code>my_stable_string</code> can be initialized later during the instance's life-cycle or not at all. But because it is detachable, <code>my_stable_string</code> cannot be accessed in any context in which it cannot be determined that it is currently attached. For ordinary attributes, this means either using an object test and accessing the object through an object test local, or using using a local variable under the protection of a CAP.
Stable attributes however, can be used directly in a CAP, as shown below:
<code>
if my_stable_string /= Void then
my_stable_string.append ("abc") -- Valid
...
</code>
So using stable attributes can reduce the need to initialize rarely used attributes, and the need to code object tests.
===Local variables===
Local variables can be used in a CAP as long as they are not the target of an assignment whose source is <code>Void</code> or some expression which could possibly be void.
So, for a local variable <code>l_string</code>, the following is valid:
<code>
local
l_string: detachable STRING
do
if l_string /= Void then
l_string.append ("abc") -- Valid
...
</code>
But, if <code>l_string</code> had been a target of an assignment in which the source could possibly have been void, then it could no longer be guaranteed that <code>l_string</code> is not void. So, assuming that <code>my_detachable_string</code> is an attribute declared as type <code>detachable STRING</code>, the second application of <code>append</code> in this example would be invalid:
<code>
local
l_string: detachable STRING
do
if l_string /= Void then
l_string.append ("abc") -- Valid
l_string := my_detachable_string
l_string.append ("xyz") -- Invalid: my_detachable_string might have been void
...
</code>
==Common CAPs==
We've already seen the simple test for void as a CAP:
<code>
local
l_str: detachable STRING
...
if l_str /= Void then
l_str.append ("xyz") -- Valid
end
</code>
Additionally, a creation instruction can serve as a CAP. After the execution of a creation instruction, the target of the creation instruction will be attached:
<code>
local
l_str: detachable STRING
do
create l_str.make_empty
l_str.append ("xyz") -- Valid
...
</code>
==Less obvious cases==
There are some situations that constitute CAPs that we might not think of immediately.
For example, the case of the non-strict boolean operator <code>and then</code>:
<code>
if x /= Void and not x.is_empty then -- Invalid
...
if x /= Void and then not x.is_empty then -- Valid
...
</code>
Assuming that <code>x</code> is CAP-able, the first line of code is invalid because the expression <code>x.is_empty</code> could always be evaluated even in the case in which <code>x</code> is void.
In the second line of code, the non-strict boolean is used, guaranteeing that <code>x.is_empty</code> will not be evaluated in cases in which <code>x</code> is void. Therefore, <code>x.is_empty</code> falls within the scope of the void test on <code>x</code>.
In contracts, multiple assertion clauses are treated as if they were separated by <code>and then</code>. This allows preconditions like the one in the following example:
<code>
my_routine (l_str: detachable STRING)
require
l_str /= Void
not l_str.is_empty -- Valid
...
</code>
Another not-so-obvious CAP is related to the use of the logical implication:
<code>
local
l_str: detachable STRING
do
if l_str /= Void implies some_expression then
...
else
l_str.append ("xyz") -- Valid
end
</code>
==The bottom line on CAPs==
In summary, CAPs provide void-safe protection for certain types of detachable expressions.
Possibly the characteristic of CAPs which is most important to developers is whether or not a particular CAP is supported by the compiler. In other words, from the developers viewpoint, the only opinion that matters in the argument of whether a particular pattern constitutes a CAP is that of the compiler.
If the compiler can provide assurance that a certain code pattern guarantees void-safe protection, then the developer will have that pattern available as a CAP. Likewise, even if a pattern can be shown logically to be a CAP, but for some reason it is not supported by the compiler, then that pattern will not available as a CAP and the compiler will not allow its use.

View File

@@ -0,0 +1,80 @@
[[Property:title|Common myths and misconceptions about Eiffel]]
[[Property:link_title|]]
[[Property:weight|4]]
[[Property:uuid|056c0ab0-8e44-571f-f126-0b1850980754]]
Often, when we speak about Eiffel to prospective users, we hear them repeat misinformation about the method, the language, or the tools. Most of the time, the stories are familiar to us … and untrue. Here are a few of the myths that we hear most often, as recounted and debunked by the series entitled [http://eiffel.com/developers/presentations/ "Where Eiffel Fits"].
==Eiffel is an "academic" language only: ''Whoa, wrong! Twice!''==
Recently, I was offered the opportunity to speak to a local technology group about Eiffel for Microsoft .Net. The leader of this group is part of a small commercially-oriented software development company. Concerning Eiffel, he said, “All I know about Eiffel is that its an academic language.”
We hear that one a lot … and its wrong … in two unrelated ways.
First, as you should know by now, Eiffel is a framework for software development. It has a full-lifecycle development method. The Eiffel method is supported by a notation we call the Eiffel programming language. The notation just happens to be designed such that when it contains sufficient detail, it can be compiled into a running software system. Additionally, the method and language are supported by a set of tools including an interactive development and compiler. So to refer to Eiffel only as a "language" is to do injustice to the complete framework of which the language is only one part.
Secondly, Im not sure what “academic language” means exactly, but if it means only used in an academic setting, or not fit for practical work, then this could not be farther from the truth. It is true that Bertrand Meyer who developed the original Eiffel concepts has academic background and is well-respected in the academic community. Its also true that many of those Eiffel ideas evolved from work that was done by other academic computer scientists and mathematicians. And its true that many colleges and universities use Eiffel to teach the best practices of software development.
But Eiffel is also used successfully in many commercial and government endeavors. If you have any doubts, pay a visit to [https://www.eiffel.com/company/customers/testimonials/ eiffel.com] and check out the success stories and customers testimonials.
==Eiffel is not for doing "real" work: ''That's a joke, right?''==
Occasionally weve heard people say that Eiffel is only suitable for building “toy” systems.
This is similar to the "academic language" argument and is just as false.
In actuality, we see Eiffel being used often in situations in which other technologies fail. If anything it is the other commonly used technologies that tend to break down under stress.
We see Eiffel being used instead of other technologies for systems in which scalability and reliability are essential.
One of our customers is an organization that has developed a payroll system using Eiffel that every week pays over two hundred thousand employees in twenty thousand different institutions … the people in this organization would assure you that Eiffel is indeed industrial grade.
==Not many people are using Eiffel: ''You wouldn't want to share an elevator with them all!''==
The answer to this one depends a bit upon your frame of reference. Some time ago Microsoft estimated that there were twenty million Visual Basic programmers world wide.
If this is true, then relatively speaking, we have to admit that Eiffels market share ''is'' considerably smaller than that of Visual Basic.
Despite that, its not correct to say that not many people use Eiffel. Eiffel licenses world wide number in the tens of thousands. If you use Eiffel, you are not alone. These license-holders have formed a lasting worldwide quorum. Many world-class organizations are committed now, and will continue to be committed to the Eiffel framework. There is support through your maintenance contract with Eiffel Software. Help and information are available online in the form of the [https://www.eiffel.com/company/customers/ Eiffel Software users list] and websites like [http://community.eiffel.com/room/ EiffelRoom].
Eiffel Software's dual licensing model gives developers the opportunity to learn Eiffel without a great initial financial commitment.
So, dont worry about it, plenty of people use Eiffel … and those numbers are increasing constantly.
==If we use Eiffel, we may not be able to find qualified programmers: ''Gimme a break.''==
Through the years some potential Eiffel users have expressed to us a concern that if they embrace Eiffel, that they may not be able to find a sufficient number of qualified developers.
This is of course incorrect.
First, almost all Eiffel people were proficient in some other technology before they became Eiffel people. It turns out that this really works to your advantage. You see, Eiffel people want to stay Eiffel people. So an Eiffel programmer on the job market will be searching for an Eiffel position first, and would probably rather have a root canal than to go back to working in his or her previous technology.
Additionally, it is important also to understand that Eiffel developers are easy to create. Because Eiffel is simple, clean, and elegant, it doesnt take long to get people going with it. I teach a five-day course that contains fifteen programming exercises. Each time Ive taught the course, almost every student has finished every exercise. Students leave with a good foundation for how to begin saving time and money for their organization by constructing quality software with Eiffel. These people can be fluent in Eiffel in as little as a couple of months. This can be contrasted with the other extreme ... a well-known Microsoft Windows expert told me a couple of years ago that he estimates it to take 5 to 7 years to become truly fluent in C++/COM programming on Windows. Programmers who are proficient in other technologies often experience Eiffel as a breath of fresh air.
==Eiffel might not be around in five/eight/ten (choose one) years: ''Better recalibrate your crystal ball, Nostradamus!''==
I think the first time I heard this one, it was about 1989.
And of course, Ive heard it many times in the years since.
And of course, its not true.
Eiffel is more complete and functionally superior in most ways to every other commercially viable software development technology … and there are enough people around who recognize this (that quorum of users I mentioned earlier) to ensure that Eiffel will be around for a long time to come.
Its possible that twenty-five years from now, there will be a significantly better software engineering idea … but certainly there hasnt been anything thats come close since Eiffels original design in 1985. In most areas, other technologies are playing “catch-up” to Eiffel.
Besides, Eiffel constantly implements refinements and new capabilities with minimal impact on existing software. [[Void-safe programming in Eiffel|Void-safe programming]] is an excellent example of this.
You can get a feel for this issue by watching [http://channel9.msdn.com/posts/Charles/Emmanuel-Stapf-Eiffel-and-Contract-Oriented-Programming/ this video on Microsoft Developers Network Channel9]. Here you'll see Emmanuel Stapf, an engineer at Eiffel Software, speak with Mads Torgersen, one of Microsoft's C# language designers. You'll hear how Eiffel stays fresh and continues to set a technological standard worthy of the aspirations of other technologies.
So, dont worry about it. Eiffel will be here.

View File

@@ -0,0 +1,97 @@
[[Property:title|Two-Minute fact sheet]]
[[Property:weight|0]]
[[Property:uuid|f672bfb8-ddea-beb1-eaa6-e374a6a6bc92]]
If you are both curious about Eiffel and in a hurry, take a couple of minutes to read these facts about Eiffel. If anything here seems too good to be true, please suspend your disbelief. Press on to the more detailed documentation for the rationale, and our success stories for the evidence behind these facts.
===Eiffel is the most comprehensive approach to the construction of successful object-oriented software.===
Software produced with Eiffel is typically:
*Cheaper -- You spend less on development, debugging, maintenance
*Better -- You get the bugs before they get you
*Shorter time-to-market -- You release quality products ahead of your competitors
*Easier -- In every way: understanding, maintenance, reuse, and extension
===Systems developed using Eiffel can be made portable across major industry platforms.===
*Windows NT/2000/XP/Vista including CLS compliance on Microsoft .NET
*Major Unix versions
*Macintosh OS X
*Linux
*OpenVMS
===Eiffel is the only approach that covers analysis, design, implementation and maintenance in a single framework.===
Eiffel consists of:
====The Eiffel Method====
*Is Based on a small number of powerful ideas from computer science and software engineering
**An example of these is Design by Contract
***Defines a software system as a set of components interacting through precisely specified contracts
***Contracts are active and enforceable throughout the life-cycle
***Design by Contract promotes:
****Precise software specification
****Software reliability
****Safe, effective software reuse
*Uses a "single-product" model
**All life-cycle phases are supported by a single notation
***No need to switch, say, from "analysis language" to "design language"
**Products of all phases are recorded in a single document with multiple views
====The Eiffel Programming Language====
*Exists to express the products of the Eiffel Method
*Supports features not always available in competing technologies
**Contracts and contract monitoring
**Exception handling based on software specification (versus ad hoc try/catch)
**Void-safety: calls on void (null) references are eliminated at compile time
**Inheritance
***Includes multiple and repeated inheritance
***Safe and fully controllable
**Genericity (generic classes), including constrained genericity
**Platform independent concurrency ([[Concurrent programming with SCOOP|SCOOP]])
*Widely recognized as simultaneously the simplest and most complete implementation of object-oriented concepts
*Is clean, elegant, readable, easy to learn
====EiffelStudio and the Eiffel Libraries====
*'''EiffelStudio'''
**Runs on all major platforms (of course, it's built with Eiffel)
**Features lightning-fast compilation (Melting Ice Technology)
**Generates lightning-fast executables
***Final compilation generates standard C (MSIL in the case of .NET)
***Speed of executables rivals native C
**Provides multiple views of your product
***Views for different life-cycle phases and developer roles
***Graphical views
**Features automated generation HTML and XML documentation
*'''The Eiffel Libraries'''
**Contain rich, time-tested, multi-platform components
**Include facilities for
***GUI building and graphics
***Web
***Networking
***Fundamental algorithms and data structures
***Object persistence and database access
***Multi-threading
***Lexical analysis and parsing
***Interfacing with other technologies
===Eiffel has a proven track record of successful projects===
*Some of the largest successful object-oriented projects ever built, including systems target to:
**Finance and securities
**Education
**Trading
**Manufacturing
**Telecommunications
**Government and national defense
**Science
For a more detailed overview see [[Invitation to Eiffel (I2E)|An Invitation to Eiffel]] .

View File

@@ -0,0 +1,5 @@
[[Property:title|Eiffel Overview]]
[[Property:link_title|Overview]]
[[Property:weight|1]]
[[Property:uuid|f65e67ed-0990-4638-b8f8-0fc85c28f0d8]]

View File

@@ -0,0 +1,54 @@
[[Property:title|Learning Eiffel]]
[[Property:weight|3]]
[[Property:uuid|a30e29fe-841d-4634-ded2-88ae1754e5fd]]
If you are new to Eiffel and are interested in learning the technology, you might consider some of the following resources. Remember that Eiffel, unlike other programming languages, is not just a programming language. Instead, it is a full life-cycle framework for software development. As a consequence, learning Eiffel implies learning the Eiffel Method and the Eiffel programming Language. Additionally, the Eiffel development environment EiffelStudio is specifically designed to support the method and language. So having an understanding of the method and language helps you to appreciate the capabilities and behavior of EiffelStudio.
=Online presentations=
Your first stop in getting acquainted with Eiffel might be the collection of [http://eiffel.com/developers/presentations/ online presentations] on the [http://eiffel.com eiffel.com] website. These presentations each usually take less than an hour to view, and give an introduction to Eiffel concepts including Design by Contract, the EiffelStudio development environment, and includes several presentations that describe selected Eiffel features in relation to those of other other development tools.
=Online documentation set=
The [http://docs.eiffel.com docs.eiffel.com] site contains the online documentation for the Eiffel method, tools, and language. Within the documentation set are tutorials to help you learn about the Eiffel programming language and tools.
==The Eiffel Tutorial==
A [[An Eiffel Tutorial (ET)|tutorial]] that covers the Eiffel Method and much of the Eiffel programming language.
==The EiffelStudio Guided Tour==
This [[Introducing EiffelStudio]] page is good way to get a feel for what EiffelStudio can do.
=Academic materials available online=
Many colleges and universities use Eiffel to teach "best practices" in software engineering. Often the materials used in courses are available on the worldwide web. For example, the teaching materials for courses at the Swiss Federal Institute of Technology in Zurich are available at [http://se.ethz.ch/teaching/index.html this web address].
If you search the web, you can find similar materials at other academic institutions.
=Learning maps=
For certain specific areas of learning, the eiffel.com website includes conceptual [http://eiffel.com/developers/learning_maps/ learning maps]. These are graphical maps that link concepts with their relationships. Each concept can have multiple learning resources attached to it. One of the most prevalent types of resources is the "Learnlet", a short online presentation (less than 30 minutes) covering a specific concept.
=Books=
To find information about the most up-to-date books about Eiffel, look [[Books about the Eiffel Method and Language|here]].
=Examples and sample code=
Throughout the documentation site, there are many code snippets designed to illustrate certain language features or design principles. For example, the code snippet [[ET: Inheritance#Redefinition|here]] shows the mechanics of redefining an inherited feature.
In the EiffelStudio distribution you will find a subdirectory "<code>examples</code>" which contains many examples of using Eiffel, primarily with the Eiffel class libraries.
A third source of examples is the [[Examples]] book in the documentation pages.
=Eiffel Programming Language Syntax=
The documentation site includes a summary of the [[Quick reference to the Eiffel programming language|syntax of Eiffel]] the language. This summary is intended to reflect the state of the current official [[ECMA Standard 367|ISO/ECMA Eiffel standard document]].
However, usually you will find that there are differences in the syntax supported by EiffelStudio's compiler and that defined in the current standard. The differences between the standard and the EiffelStudio implementation are summarized in the [[EiffelStudio release notes]] and in a [[Differences between standard ECMA-367 and Eiffel Software implementation|documentation page]] that is specific to that purpose.

View File

@@ -0,0 +1,185 @@
[[Property:title|Your next project in Eiffel]]
[[Property:weight|1]]
[[Property:uuid|038CDA4A-9ACA-46F6-AC10-06942FAE4529]]
(After an article in the special Eiffel issue of the ''Journal of Object-Oriented Programming'', May 1996.)
Over its ten-year life Eiffel has evolved into one of the most usable software development environments available today. Other articles discuss its theoretical contributions. This one addresses a more mundane subject: how practical software projects can benefit, today, from the power of Eiffel. In so doing it will largely rely on published assessments from both Eiffel users and book authors. In fact a quotation from one of the best-known books in the object-oriented field -- ''Object-Oriented Modeling and Design'' by James Rumbaugh and his colleagues, the text that introduced the OMT O-O analysis method -- provides a good start:
<blockquote>
''Eiffel is arguably the best commercial object-oriented language available today. [Jim Rumbaugh et al. in Object-Oriented Modeling and Design, Prentice Hall 1988]. ''
</blockquote>
==What is Eiffel?==
First we should define what the word "Eiffel" means. If you are thinking "a programming language" you are not wrong (and the preceding quotation shows that you are in good company). The programming language is indeed the most visible part, but it is only a reflection of something broader: a comprehensive approach to the production of quality software. As Richard Wiener wrote:
<blockquote>
''Eiffel is more than a language; it is a framework for thinking about, designing and implementing object-oriented software. [Richard Wiener in Software Development using Eiffel: There is life other than C++, Prentice Hall, 1995.] ''
</blockquote>
The Eiffel approach includes a method (a "methodology", as it is sometimes called) based on a number of pervasive ideas such as Design by Contract, seamlessness, reversibility, rigorous architectural rules, systematic use of single and multiple inheritance, static type checking and several others. Besides a method and a language Eiffel also means powerful graphical development environments, such as EiffelStudio, available across a wide number of industry-standard platforms and supporting analysis and design as well as implementation, maintenance and evolution.
The language itself, indeed (which Wiener calls an elegant and powerful language for object-oriented problem solving") is not just a programming language but extends to the phases of system construction that both precede and follow implementation. This is sometimes hard to accept if you have been raised in the view that software development must involve a sequence of separate steps; that one should initially use an analysis method and then at some point switch to a programming language, with perhaps a design method in-between. This view is detrimental to the software process and to the quality of the resulting product, as it does not support the inevitable back-and-forth hesitations that characterize real software development.
Wisdom sometimes blooms late in the season. However careful you may have been at the analysis stage, some great ideas will hit you - or your implementers - past the point at which you thought you had all the specifications right. Why renounce the benefit of such belated but valuable ideas? Eiffel and the associated Business Object Notation approach to analysis and design accommodate them naturally, by providing a single conceptual framework from the beginning to the end of the process.
Here Eiffel does not have much competition. The most bright-eyed Smalltalk or C++ enthusiast would not seriously claim that one can do design, let alone analysis, in his language of choice. And users of any of the popular O-O analysis notations know that at some stage they must stop working on their model and move on to the implementation in some programming language. Eiffel is unique in helping you for all of these tasks, without ever introducing the impedance mismatches that characterize other approaches.
As a reviewer wrote:
<blockquote>
''As a design language, Eiffel continues to be a better model for object- oriented programming than Ada. It is even better than the new Ada 9X standard. [Richard Riehle in HP Professional, October 1994, A Tour of Eiffel.] ''
</blockquote>
==The commercial and political context==
The next few sections give a glimpse of the technical contributions of Eiffel, or more precisely of what other people have written about them. But of course the best technology in the world requires infrastructure and support to succeed.
Eiffel has plenty of these. It has been around for more than a decade. Eiffel is available from several commercial and open-source providers. The number of licenses sold is in the tens of thousands. Reusable library classes are in the thousands.
The platforms covered range from Unix (all of Unix, the famous and the arcane) and Linux to OpenVMS, OS/2, Windows 3. 1, Windows NT, Windows 95/98.
Particularly impressive is the growth of Eiffel usage in education. Eiffel is quickly becoming the language of choice for teaching modern software technology, including, increasingly, introductory programming. A dozen of excellent textbooks are now available from Prentice Hall, Addison-Wesley, Macmillan and others, with about as many announced just for the coming months.
It is not just the professors who like the approach. Here is just one typical comment on student reaction, from an institution (Rochester Institute of Technology) having adopted Eiffel as its first-year introductory language on a massive scale:
<blockquote>
''We were pleased to discover many of our more skeptical students turning around and admitting that Eiffel was a "fun" language in which to work. [Jim Heliotis in the Proceedings of OOPSLA 95, Experiences teaching objects: A new curriculum for computer science students.] ''
</blockquote>
A Computer World article confirmed the need for Eiffel in training the high-powered software professionals of tomorrow. Quoting Amy Cody-Quinn from Management Recruiters International, the journalist writes
<blockquote>
''There is a big problem with people who say they know C++ - but they don't really know how to do objects. If they have Eiffel on their resume, then we know they really have the proper understanding of what they are doing. [Leslie Goff in ComputerWorld, Object Edge, December 18, 1995.] ''
</blockquote>
But it would be a mistake to think of Eiffel as an academic tool. A little-known fact is that some of the biggest object-oriented projects ever undertaken (at least the successful ones - other O-O languages have had their share of large-scale failures) are being done in Eiffel. The hot areas at the moment are banking and the financial industry (in particular some very large derivative trading and investment management systems), telecommunications, health care. These are all areas in which all that counts in the end is quality and time to market, so that projects need to select the best technology available. Quoting from an article by Philippe Stephan, the system architect of such a project (Rainbow, a major derivative trading system built with ISE Eiffel):
<blockquote>
''We evaluated three major object-oriented languages for the project - Smalltalk, C++ and Eiffel - and chose Eiffel. [...] Rainbow currently comprises over 400,000 lines of code, for about 3000 classes. [Current figures are way over these mid-1995 counts. ] The developers feel very productive. This was confirmed when Rainbow's financial backers brought in object professionals to audit the project. The auditors evaluated the project during July 1994 and were impressed with the productivity of the Rainbow development group. [Philippe Stephan in Object Magazine, July-August 1995, Building financial software with object technology.] ''
</blockquote>
The development group in question is remarkable for being made only for a third of software professionals. The others are professionals from other disciplines (such as trading and financial analysis), who, Stephan writes,
<blockquote>
''can express business concepts in Eiffel because they can focus on design and implementation, rather than struggling with memory management problems and debugging. ''
</blockquote>
The result has received lavish praise from such publications as ComputerWorld and analysts:
<blockquote>
''Industry experts briefed on Rainbow said they were impressed with the results. CALFP is "progressive" in [...] committing the organization's mission-critical systems development efforts to this architecture, said Richard Crone, senior manager of financial services at KPMG Peat Marwick in Los Angeles. "What's unique here is that [CALFP is] delivering this system end-to-end using object-oriented technologies", said Henry Morris, a research analyst at International Data Corporation (IDC) in Framingham, Mass. [Thomas Hoffmann in ComputerWorld, May 8, 1995, Object- Oriented financial package tames transactions.]''
</blockquote>
Along with these Eiffel mega-projects, you will also find myriad smaller endeavors. Many consultants, in particular, have found for themselves the key competitive advantage that they can gain from Eiffel's excellence. In ensuring this spread of Eiffel throughout the industry, the benefit of cheap yet complete environments such as EiffelStudio for Linux has been immeasurable.
Also crucial to the development of Eiffel has been the neutral status of its definition, now controlled by a consortium of vendors and users, NICE (the Nonprofit International Consortium for Eiffel). NICE has already produced a library standard and expects to produce soon the language standard that should shortly thereafter enjoy a smooth ride through ANSI and other international standards bodies.
The pace of Eiffel history has been accelerating in the past few months. This has been picked up by many journalists. As Dan Wilder wrote:
<blockquote>
''With an open specification for both the language and the kernel libraries, and support from multiple vendors, Eiffel now stands poised to take off. [Dan Wilder in Linux Journal, June 1995, Introduction to Eiffel.] ''
</blockquote>
==The criteria==
Eiffel - the method, the language, the environment - is based on a small set of goals, addressing the crucial needs of software quality and productivity. Quoting from an article in ''Byte'' magazine:
<blockquote>
''Developers who want an object-oriented language that adheres to the keystone principles of software engineering need look no further than Eiffel. [Peter Varhol in Byte Magazine, February 1996.] ''
</blockquote>
or, as Steve Bilow wrote in a review of Eiffel Software's Melting Ice compiling technology (which he calls "an outstanding marriage between portability and development speed"):
<blockquote>
''Eiffel was designed precisely for the purpose of enabling software developers to deliver high quality, reliable, efficient, reusable code. [Steve Bilow in The X Journal, The Eiffel alternative, July-August 1995.]''
</blockquote>
==Reliability==
The first goal is reliability. No other approach available today has made the effort to give developers all the tools that they need to produce bug-free software - software that will run without bugs the first time around. Crucial in this effort is the presence of static typing ( ''real'' static typing, not "a little bit typed" as in those languages that still keep C-like type conversions); assertions and the whole mechanism of Design by Contract, on which more than one Eiffel developer has said "this has changed my life" by enabling him or her to specify precisely what the software should do, and to track at run time that it does it; disciplined exception handling; automatic garbage collection, which eliminates a source of horrendous bugs in C++-based environments (and a large part of the code, tedious and error-prone); a clean approach to inheritance; the use of dynamic binding as the default policy, meaning the guarantee that all calls will use the right version of each operation; and the simplicity of the language design, which enables Eiffel developers to know '''all''' of Eiffel and feel in control.
The role of assertions and Design by Contract is particularly important here. According to the ''Journal of Object-Oriented Programming'':
<blockquote>
''The contribution of Eiffel is significant: it shows how invariants, preconditions, and postconditions can be incorporated into a practical developer's view of a class. Wider use of Eiffel [...] will encourage a greater use of simple but powerful mathematics during development. [Richard Mitchell et al. in Journal of Object-Oriented Programming, July-August 1995, As-a: a relationship to support code reuse.] ''
</blockquote>
==Reusability==
The second goal is reusability. This has become a catchword, but Eiffel is the only approach that has taken this requirement and its consequences all the way to the end. Quoting Roland Racko:
<blockquote>
''Everything about [Eiffel] is single-mindedly, unambiguously, gloriously focused on reusability - right down to the choice of reserved words and punctuation and right up to the compile time environment. [Roland Racko in Software Development, December 1994, In praise of Eiffel.] ''
</blockquote>
Eiffel benefits here from being a simple ("but not simplistic", writes Racko) and consistent design, not a transposition from older, unrelated technology. Beyond the language and the environment facilities (such as precompilation), the crucial help to reusability is of course the presence of thousands of high-quality library ''classes'', such as, in EiffelBase (a "Linnaean approach to the reconstruction of software fundamentals"), EiffelNet for client-server communication, EiffelStore for relational and O-O database manipulations, EiffelLex and EiffelParse for lexical analysis and parsing, EiffelMath for object-oriented numerical computation, EiffelVision for portable graphics, WEL (the Windows Eiffel Library) for Windows-specific graphics, EiffelWeb to process forms from the Web, and many others. Not even mentioning quality, the result is probably the biggest repository of object-oriented components available elsewhere. The care that has been applied to the production of these libraries also has considerable pedagogical benefits: the way people learn Eiffel is by learning the libraries - first to use them, then to adapt them if necessary, then to write their own software.
Part of the single-mindedness mentioned by acko is the emphasis on abstraction. In contrast with, say, Smalltalk, you do not read the source code of a class when you want to use it. This may be fine for a couple dozen classes, but not for a large, powerful library. Eiffel introduces the notion of '''short form''': an abstract version of the class, keeping only the interface information including assertions. This is an ideal tool for documenting classes but also for discussing designs and presenting them to outsiders - managers or customers - who need to know what is going on without getting bogged down in the details.
Let me mention just one of the unique reusability-supporting features of Eiffel, without which it is, in my experience, impossible to have a long-term reuse effort. Racko again:
<blockquote>
''The language's designer [...] recognized that no reusable library is ever perfect and, thus, that libraries are always in flux. So he built a kind of version-control system into the language. Specifically, there are language elements to demarcate obsolete code that is, however, still being supported. When these elements are referenced by someone unaware of such code's obsolescence, the compiler will issue a warning at compile time about the impending doom that awaits persons who continue the referencing. ''
</blockquote>
It is this kind of detail that can make or break the success of reuse in a company.
==Extendibility==
Next comes extendibility. With Eiffel, modifying software is part of the normal process. As Philippe Stephan writes of the external audit of his project:
<blockquote>
''The auditors rated the responsiveness of the development team as very high. ''
</blockquote>
Chief among the method's support for extendibility is the careful design of the inheritance mechanism. Unlike Smalltalk, which is fatally limited by the absence of multiple inheritance, the Eiffel approach fundamentally relies on multiple inheritance to combine various abstractions into one. As Dan Wilder notes:
<blockquote>
''Most object-oriented languages do not attempt multiple-inheritance. The literature is full of elaborate explanations why. This is sad. Eiffel demonstrates that multiple inheritance need not be difficult or complex, and it can also yield some quite practical results. ''
</blockquote>
The approach also enforces a strict form of information hiding, which means that a module (a '''client''' in Eiffel Design by Contract terminology) that uses another's facilities (its '''supplier''') is protected against many of the changes that can be made later on to these facilities. This is essential in preserving the coherent evolution of a large system - and the sanity of its developers.
==Efficiency==
Performance is almost as much an obsession in Eiffel as reusability. The software field is still, and will remain for a long time, largely driven by performance considerations. (Do not believe anyone who says that speed does not matter. If we get faster computers, it is to do things faster and especially to do more things - not to use more CPU cycles to run the same old applications at the same old visible speed. )
There is no reason whatsoever to leave the mantle of efficiency to the proponents of machine-oriented languages such as C/C++, or to follow the path of Smalltalk which sacrifices performance to object orientation. With Eiffel you can have the best of both worlds. Thanks to a performance-obsessed language design and ten years of research and competition on compiling algorithms, the speed of Eiffel-generated code (in such modes as what is known as "finalization" in Eiffel Software's implementation) is as good as that of hand-produced C code, or better.
Software producers should stand up to their ideas. That is what we do at Eiffel Software: apart from the run-time engine (a few thousand lines of C), all of our software - thousands of classes, hundreds of thousands of lines - is written in Eiffel, and it runs fast. Typical of the situation is a recent incident with the EiffelLex library: it still had a few C elements, remnants of an earlier design. We rewrote them in Eiffel - for a 30% performance gain.
Why these gains? The answer is simple. The /C++ approach of doing everything by hand, under tight programmer control, works well for small programs. Similarly, a good secretary has no equivalent for keeping one person's records. But in the same way that no humans can match the performance of a computer for managing, say, the records of a bank or a city, no programmer can beat a sophisticated Eiffel compiler for optimizing a large program. Against the automatic application of inlining, static binding, memory management and other optimizations, the human does not stand a chance.
To have one's cake and eat it also means not to have to choose between run-time and compilation-time performance. For programmers used to the contrast between a Smalltalk-like style of rapid turnaround and the interminable edit-compile-link cycle of most compiled environment, the following comments by Dan Wilder (in a separate article) will be a shock:
<blockquote>
''EiffelStudio uses "melting ice technology", which allows incremental changes to run in an interpreted mode. Only modified classes are recompiled. Changing one class and clicking the Melt button caused only a few seconds of compilation. [...] My test application took 20 seconds to compile from scratch in "melt" mode. [Dan Wilder in Linux Journal, September 1995, Two Eiffel implementations.] ''
</blockquote>
Steve Bilow provides further explanations:
<blockquote>
''Based on the observation that software development is an iterative process which is usually focused on constructing systems from code modifications, the folks at Eiffel Software have developed something that they call "Melting Ice Technology". Essentially, this means that when you make a [change] and you want to try it out, you simply "melt" it into the system. You don't need to regenerate a bunch of C code, so your changes are integrated into the system proportionally to the amount of code changed. Even in C and C++, `make` still has to relink. ''
</blockquote>
What this also indicates in passing is the technology choice made by Eiffel Software's implementation and all current implementations: using C as the portable implementation vehicle. By going through C, the compilers gain efficiency and portability. This also makes Eiffel one of the most open environments around; in contrast to the self-centered view that predominates in Smalltalk, Eiffel software is born with a sociable attitude, ready to interface with all kinds of other software written in C or other languages. This, needless to say, is a key to the success of realistic applications.
==With us, everything is the face==
A good way to think about Eiffel - the seamlessness of it, the insistence on getting everything right, the conviction that software should be beautiful in and out, specification and implementation - is this little anecdote stolen from Roman Jakobson's Essays on ''General Linguistics'':
<blockquote>
''In a far-away country, a missionary was scolding the natives. "You should not go around naked, showing your body like this!". One day a young girl spoke back, pointing at him: "But you, Father, you are also showing a part of your body!". "But of course", the missionary said in a dignified tone; "That is my face". The girl replied: "So you see, Father, it is really the same thing. Only, with us, everything is the face". ''
</blockquote>
So it is with Eiffel too. Everything is the face.
Hundreds of thousands of people have now been exposed to Eiffel through books, through courses, through hearing about other people's successes, and most importantly (for the most fortunate among them) through using it to complete a project on time, within budget, and to the satisfaction of their customers. Shouldn't your next project use Eiffel too?

View File

@@ -0,0 +1,16 @@
[[Property:title|ECMA Standard 367]]
[[Property:weight|1]]
[[Property:uuid|b49b0949-85fa-31da-555e-003b09f6213e]]
[[Image:ECMA-367 cover small|ECMA-367]]
==ECMA Standard 367 -- Eiffel: Analysis, Design, and Programming Language==
ECMA International
Standard Eiffel syntax, validity, and semantics are described in this document, which is available [http://www.ecma-international.org/publications/standards/Ecma-367.htm online].
ECMA-367 is a specification for the Eiffel programming language. Therefore, it can be useful as a reference, but it is definitely not a tutorial. That said, the document does contain occasional informative text and a general description chapter which can help readers understand the specification.

View File

@@ -0,0 +1,26 @@
[[Property:title|Eiffel: The Language]]
[[Property:weight|2]]
[[Property:uuid|dae5a248-29f5-02b2-d01f-371394aa75e9]]
[[Image:ETL]]
=='''''Eiffel: The Language''''' by Bertrand Meyer.==
Prentice Hall Object-Oriented Series.
594 pp.
Soft cover.
<nowiki>ISBN 0-13-247925-7</nowiki>
''Eiffel: The Language'' is one of the foundation volumes of Eiffel technology. It was originally published in 1992, and reprinted later with updates and corrections.
Because the language specification has changed since the last reprinting to incorporate new quality and productivity constructs, hardcopies of ''Eiffel: The Language'', although still available, will represent the bulk of Eiffel correctly, but will not reflect the latest important changes.
Currently ''Standard Eiffel'', the successor to ''Eiffel: The Language'', is a work-in-progress and is available in its current state online (See ''Standard Eiffel'', on [http://se.ethz.ch/~meyer/publications/#PSTE this page]).
The most current state of Eiffel syntax, validity, and semantics is described in the ISO/ECMA [http://www.ecma-international.org/publications/standards/Ecma-367.htm standard document], also available online.

View File

@@ -0,0 +1,6 @@
[[Property:title|Books about the Eiffel Method and Language]]
[[Property:link_title|Books]]
[[Property:weight|5]]
[[Property:uuid|721967da-6621-33f0-198f-9fc8ee26d37f]]

View File

@@ -0,0 +1,39 @@
[[Property:title|Object-Oriented Software Construction, 2nd Edition]]
[[Property:link_title|OOSC2]]
[[Property:weight|0]]
[[Property:uuid|496983ef-b86e-772e-16b9-39b37ef80e37]]
[[Image:OOSC2 small|OOSC2]]
=='''''Object-Oriented Software Construction, 2nd Edition''''' by Bertrand Meyer.==
Prentice Hall Professional Technical Reference.
1254 + xxviii pp.
Soft cover.
<nowiki>ISBN 0-13-629155-4</nowiki>
Click to [http://www.amazon.com/Object-Oriented-Software-Construction-Book-CD-ROM/dp/0136291554 buy from Amazon].
This Jolt Award winner takes the reader through the clear, logical, and comprehensive formation of a method for object-oriented software development ... the Eiffel method. During this journey, the author evolves a notation capable of expressing the products of each phase of development, from analysis through implementation. This notation is the Eiffel programming language.
==Praise for '''''Object-Oriented Software Construction, 2nd Edition'''''==
Roger Smith, on the Dr. Dobbs Journal website, writes:
:"In my unbiased opinion [...] it is destined to become the comprehensive and definitive reference for most methodological and technical questions raised by object technology. Its width and breadth of scope is impressive, from object-oriented techniques like Design by Contract and inheritance, to methodology issues like patterns and class design, to advanced issues like concurrency and persistence."
In ''Unix Review'', Stan Kelly-Bootle calls this book "The ultimate O-O guide."
Ian Graham, in ''Journal of Object-Oriented Programming'' calls it "Epoch-making".

View File

@@ -0,0 +1,36 @@
[[Property:link_title|Touch of Class]]
[[Property:title|Touch of Class: Learning to Program Well with Objects and Contracts]]
[[Property:weight|-1]]
[[Property:uuid|3b4afd2f-6433-c619-f9a4-602c430c6902]]
[[Image:Touch of Class cover small]]
=='''''Touch of Class: Learning to Program Well with Objects and Contracts''''' by Bertrand Meyer==
Springer-Verlag, 2009
876 + lxiv pp.
<nowiki>ISBN-13: 978-3540921448 </nowiki>
Full color printing; many color illustrations and photographs
Click to [http://www.amazon.com/Touch-Class-Learning-Program-Contracts/dp/3540921443 buy from Amazon].
Is this really a book about Eiffel? Perhaps in some senses it is not. It is a book about exactly what the subtitle indicates: ''Learning to Program Well with Objects and Contracts.'' (Primary emphasis should fall on the word "''Well''".)
Still, the Eiffel method and language are used in this journey as tools, the best tools known, to help those seeking excellence in software development become prepared to meet the types of challenges a career in software will present. In the rapidly changing software world, this is a tall order. As the preface (for instructors) states:
:'' It is not enough to present immediately applicable technology, for which in our globalized industry a cheaper programmer will always be available somewhere ... [Software professionals] must master software development as a professional endeavor, and by this distinguish themselves from the masses of occasional or amateur programmers.''
''Touch of Class'' imparts its message using techniques which have accumulated through decades of study of technical learning and have been applied for several years in courses at ETH Zurich. These techniques include the extensive study and reuse of libraries of high-quality software components, employment of the Eiffel object-oriented method and Design by Contract, an introduction to formal methods and a ubiquitous awareness for software engineering concerns.
A unique and refreshing aspect of ''Touch of Class'' is seen throughout the volume. Credit is given for ideas which form the foundation of modern software thinking, and in the process, those pioneers upon whose shoulders all software professionals stand, are made human and personal by photographs and historical vignettes.

View File

@@ -0,0 +1,20 @@
[[Property:title|Eiffel as an expression language]]
[[Property:weight|0]]
[[Property:uuid|61e93102-c558-42e7-7784-0b60b9257b5d]]
A functional-programming style, or more generally a style involving more expressions and fewer instructions, is possible in Eiffel. In particular, the agent mechanism embeds a full functional-programming mechanism in the object-oriented framework of the language.
To make the notations simpler, a number of extensions have been proposed. They involve no fundamental new language mechanisms, but provide new, more concise notations for existing mechanisms. Examples are:
*Conditional expressions
*Implicit tuple, a rule allowing the omission of brackets for an actual argument when it is a tuple and the last argument, e.g. f (a, b, c) as an abbreviation for f ([a, b, c]) (an example involving just one argument). Tuples already provided the equivalent of a variable-argument ("varargs") facility, but it is made simpler to use with this convention.
*Parenthesis alias, making it possible to write just f (x, y) when f is an agent (closure, lambda expression, delegate etc. in other terminologies), i.e. treating f as if it were a function; the notation is simply an abbreviation for f.item ([x, y]) (this example also takes advantage of implicit tuples). It has many other applications since a "parenthesis alias" can be defined for a feature of any class.
*Avoiding explicit assignments to '''Result'''.
*Type inference (to avoid explicitly specifying the type when it can be deduced from the context). This is a facility for the programmer, useful in particular for local variables, but does not affect the type system: Eiffel remains strongly typed, it is just that you can be lazy about writing the type when there is no ambiguity.
*In the same vein, omitting the entire list of generic parameters when it can be inferred.
see [[file:expression_language.pdf|document as pdf]].

View File

@@ -0,0 +1,9 @@
[[Property:title|Technical papers about Eiffel]]
[[Property:description|Background, foundation, or supplemental information about uncovered topics]]
[[Property:link_title|Papers]]
[[Property:weight|4]]
[[Property:uuid|d2b880d6-d1dc-9811-32b8-ed718ad4d4be]]
Occasionally papers are produced providing background, foundation, or supplemental information about the topics covered by the Eiffel documentation. Although the material in these papers might be of interest to many Eiffel users, they might not be suitable in their current form for inclusion in the mainstream documentation books.
You will find a collection of these papers in this book.

View File

@@ -0,0 +1,25 @@
[[Property:title|Void-safety: how Eiffel removes null-pointer dereferencing]]
[[Property:weight|0]]
[[Property:uuid|d9380464-4312-b76e-9bfd-e57df0f59b4a]]
This white paper (see [[file:void-safe-eiffel.pdf|document as pdf]]) presents the Eiffel void-safety mechanism, fully implemented in EiffelStudio 6.4.
In almost every program running today there is a ticking time bomb: the risk of a "void call". A void call is possible in programs written in almost any programming language; its effect is usually to crash the program. Many unexplained program failures and other abnormal behaviors result from void calls.
While extensive testing can decrease the likelihood of a void call, it cannot remove the possibility. The solution has to come from the programming language.
<!--break-->
Professor C.A.R. Hoare from Microsoft Research, winner of the Turing Award and the Kyoto Prize, calls the presence of void calls in modern programming languages the "billion-dollar mistake":
:"The invention of the null reference in 1965" [the source of void calls] "has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years."
(Citation at: [http://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare] )
The Eiffel solution relies on a combination of language mechanisms:
*"Certified Attachment Patterns" are code schemes that the EiffelStudio compiler guarantees to be void-safe.
*"Attached types" are types that are guaranteed to have non-void values.
*The "Object Test" instruction lets programmers treat void values in a special way.
The White Paper (see the link below) describes the theoretical and practical challenges of ensuring void-safety and presents the Eiffel mechanism.

View File

@@ -0,0 +1,248 @@
[[Property:title|ET: Agents]]
[[Property:weight|-3]]
[[Property:uuid|ba49a80d-5ddf-8b30-4943-528974fd0ddd]]
Our last mechanism, agents, adds one final level of expressive power to the framework describe so far. Agents apply object-oriented concepts to the modeling of operations.
==Objects for operations==
Operations are not objects; in fact, object technology starts from the decision to separate these two aspects, and to choose object types, rather than the operations, as the basis for modular organization of a system, attaching each operation to the resulting modules -- the classes.
In a number of applications, however, we may need objects that represent operations, so that we can include them in object structures that some other piece of the software will later traverse to uncover the operations and, usually, execute them. Such "operation wrapper" objects, called agents, are useful in a number of application areas such as: <br/>
* GUI (Graphical User Interface) programming, where we may associate an agent with a certain event of the interface, such as a mouse click at a certain place on the screen, to prescribe that if the event occurs -- a user clicks there -- it must cause execution of the agent's associated operation.
* Iteration on data structures, where we may define a general-purpose routine that can apply an arbitrary operation to all the elements of a structure such as a list; to specify a particular operation to iterate, we will pass to the iteration mechanism an agent representing that operation.
* Numerical computation, where we may define a routine that computes the integral of any applicable function on any applicable interval; to represent that function and pass its representation to the integration routine, we will use an agent.
Operations in Eiffel are expressed as routines, and indeed every agent will have an associated routine. Remember, however, that the fundamental distinction between objects and operations remains: an agent is an object, and it is not a routine; it represents a routine. As further evidence that this is a proper data abstraction, note that the procedure <code>call</code>, available on all agents to call the associated routine, is only one of the features of agents. Other features may denote properties such as the class to which the routine belongs, its precondition and postcondition, the result of the last call for a function, the number of arguments.
==Building an agent==
In the simplest form, also one of the most common, you obtain an agent just by writing
<code>
agent r
</code>
where <code>r</code> is the name of a routine of the enclosing class. This is an expression, which you may assign to a writable entity, or pass as argument to a routine. Here for example is how you will specify event handling in the style of the EiffelVision 2 GUI library:
<code>
your_icon.click_actions.extend (agent your_routine)
</code>
This adds to the end of <code>your_icon.click_actions</code> -- the list of agents associated with the "click" event for <code>your_icon</code>, denoting an icon in the application's user interface -- an agent representing <code>your_routine</code>. Then when a user clicks on the associated icon at execution, the EiffelVision 2 mechanisms will call the procedure <code>call</code> on every agent of the list, which for this agent will execute <code>your_routine</code>. This is a simple way to associate elements of your application, more precisely its "business model" (the processing that you have defined, directly connected to the application's business domain), with elements of its GUI.
Similarly although in a completely different area, you may request the integration of a function <code>your_function</code> over the interval <code>0..1</code> through a call such as
<code>
your_integrator.integral (agent your_function, 0, 1)
</code>
In the third example area cited above, you may call an iterator of EiffelBase through
<code>
your_list.do_all (agent your_proc)
</code>
with <code>your_list</code> of a type such as <code>LIST [YOUR_TYPE]</code>. This will apply <code>your_proc</code> to every element of the list in turn.
The agent mechanism is type-checked like the rest of Eiffel; so the last example is valid if and only if <code>your_proc</code> is a procedure with one argument of type <code>YOUR_TYPE</code>.
==Operations on agents==
An agent <code>agent</code> <code>r</code> built from a procedure <code>r</code> is of type <code>PROCEDURE [T, ARGS]</code> where <code>T</code> represents the class to which <code>r</code> belongs and <code>ARGS</code> the type of its arguments. If <code>r</code> is a function of result type <code>RES</code>, the type is <code>FUNCTION [T, ARGS, RES]</code>. Classes <code>PROCEDURE</code> and <code>FUNCTION</code> are from the Kernel Library of EiffelBase, both inheriting from <code>ROUTINE [T, ARGS]</code>.
Among the features of <code>ROUTINE</code> and its descendants the most important are <code>call</code>, already noted, which calls the associated routine, and <code>item</code>, appearing only in <code>FUNCTION</code> and yielding the result of the associated function, which it obtains by calling <code>call</code>.
As an example of using these mechanisms, here is how the function <code>integral</code> could look like in our <code>INTEGRATOR</code> example class. The details of the integration algorithm (straight forward, and making no claims to numerical sophistication) do not matter, but you see the place were we evaluate the mathematical function associated with <code>f</code>, by calling <code>item</code> on <code>f</code>:
<code>
integral (f: FUNCTION [ANY, TUPLE [REAL], REAL]; low, high: REAL): REAL
-- Integral of `f' over the interval [`low', `high']
require
meaningful_interval: low <= high
local
x: REAL
do
from
x := low
invariant
x >= low
x <= high + step
-- Result approximates the integral over
-- the interval [low, low.max (x - step)]
until
x > high
loop
Result := Result + step * f.item ([x]) -- Here item is applied to f
x := x + step
end
end
</code>
Function <code>integral</code> takes three arguments: the agent <code>f</code> representing the function to be integrated, and the two interval bounds. When we need to evaluate that function for the value <code>x</code>, in the line
<code>
Result := Result + step * f.item ([x])
</code>
we don't directly pass <code>x</code> to <code>item</code>; instead, we pass a one-element tuple <code>[x]</code>, using the syntax for manifest tuples introduced in [[ET: Other Mechanisms#Tuple_types|"Tuple types"]] . You will always use tuples for the argument to <code>call</code> and <code>item</code>, because these features must be applicable to any routine, and so cannot rely on a fixed number of arguments. Instead they take a single tuple intended to contain all the arguments. This property is reflected in the type of the second actual generic parameter to <code>f</code>, corresponding to <code>ARGS</code> (the formal generic parameter of <code>FUNCTION</code>): here it's <code>TUPLE [REAL]</code> to require an argument such as <code>[x]</code>, where <code>x</code> is of type <code>REAL</code>.
Similarly, consider the agent that the call seen above:
<code>
your_icon.click_actions.extend (agent your_routine)
</code>
added to an EiffelVision list. When the EiffelVision mechanism detects a mouse click event, it will apply to each element <code>item</code> of the list of agents, <code>your_icon.click_actions</code>, an instruction such as
<code>
item.call ([x, y])
</code>
where <code>x</code> and <code>y</code> are the coordinates of the mouse clicking position. If <code>item</code> denotes the list element <code>agent</code> your_routine, inserted by the above call to <code>extend</code>, the effect will be the same as that of calling
<code>
your_routine (x, y)
</code>
assuming that <code>your_routine</code> indeed takes arguments of the appropriate type, here <code>INTEGER</code> representing a coordinate in pixels. (Otherwise type checking would have rejected the call to <code>extend</code>.)
==Open and closed arguments==
In the examples so far, execution of the agent's associated routine, through <code>item</code> or <code>call</code>, passed exactly the arguments that a direct call to the routine would expect. You can have more flexibility. In particular, you may build an agent from a routine with more arguments than expected in the final call, and you may set the values of some arguments at the time you define the agent.
Assume for example that a cartographical application lets a user record the location of a city by clicking on the corresponding position on the map. The application may do this through a procedure
<code>
record_city (cn: STRING; pop: INTEGER; x, y: INTEGER)
-- Record that the city of name `cn' is at coordinates
-- `x' and `y' with population `pop'.
</code>
Then you can associate it with the GUI through a call such as
<code>
map.click_actions.extend (agent record_city (name, population, ?, ?))
</code>
assuming that the information on the <code>name</code> and the <code>population</code> has already been determined. What the agent denotes is the same as <code>agent</code> <code>your_routine</code> as given before, where <code>your_routine</code> would be a fictitious two-argument routine obtained from <code>record_city</code> -- a four-argument routine -- by setting the first two arguments once and for all to the values given, <code>name</code> and <code>population</code>.
In the agent <code>agent record_city (name, population, ?, ?)</code>, we say that these first two arguments, with their set values, are '''closed'''; the last two are '''open'''. The question mark syntax introduced by this example may only appear in agent expressions; it denotes open arguments. This means, by the way, that you may view the basic form used in the preceding examples, <code>agent your_routine</code>, as an abbreviation -- assuming your_routine has two arguments -- for <code>agent your_routine (?, ?)</code>. It is indeed permitted, to define an agent with all arguments open, to omit the argument list altogether; no ambiguity may result.
For type checking, <code>agent record_city (name, population, ?, ?)</code> and <code>agent your_routine (?, ?)</code> are acceptable in exactly the same situations, since both represent routines with two arguments. The type of both is
<code>
PROCEDURE [ANY, TUPLE [INTEGER, INTEGER]]
</code>
where the tuple type specifies the open operands.
A completely closed agent, such as <code>agent your_routine (25, 32)</code> or <code>agent record_city (name, population, 25, 32)</code>, has the type <code>TUPLE</code>, with no parameters; you will call it with <code>call ([ ])</code>, using an empty tuple as argument.
The freedom to start from a routine with an arbitrary number of arguments, and choose which ones you want to close and which ones to leave open, provides a good part of the attraction of the agent mechanism. It means in particular that in GUI applications you can limit to the strict minimum the "glue" code (sometimes called the controller in the so-called MVC, Model-View Controller, scheme of GUI design) between the user interface and "business model" parts of a system. A routine such as <code>record_city</code> is a typical example of an element of the business model, uninfluenced -- as it should be -- by considerations of user interface design. Yet by passing it in the form of an agent with partially open and partially closed arguments, you may be able to use it directly in the GUI, as shown above, without any "controller" code.
As another example of the mechanism's versatility, we saw above an integral function that could integrate a function of one variable over an interval, as in
<code>
your_integrator.integral (agent your_function (0, 1))
</code>
Now assume that <code>function3</code> takes three arguments. To integrate <code>function3</code> with two arguments fixed, you don't need a new <code>integral</code> function; just use the same <code>integral</code> as before, judiciously selecting what to close and what to leave open:
<code>
your_integrator.integral (agent function3 (3.5, ?, 6.0), 0, 1)
</code>
==Open targets==
All the agent examples seen so far were based on routines of the enclosing class. This is not required. Feature calls, as you remember, were either unqualified, as in <code>f (x, y)</code>, or qualified, as in <code>a.g (x, y)</code>. Agents, too, have a qualified variant as in
<code>
agent a.g
</code>
which is closed on its target <code>a</code> and open on the arguments. Variants such as <code>agent a.g (x, y)</code>, all closed, and <code>agent a.g (?, y)</code>, open on one argument, are all valid.
You may also want to make the target open. The question mark syntax could not work here, since it wouldn't tell us the class to which feature <code>g</code> belongs, known in the preceding examples from the type of <code>a</code>. As in creation expressions, we must list the type explicitly; the convention is the same: write the types in braces, as in
<code>
agent {SOME_TYPE}.g
agent {SOME_TYPE}.g (?, ?)
agent {SOME_TYPE}.g (?, y)
</code>
The first two of these examples are open on the target and both operands; they mean the same. The third is closed on one argument, open on the other and on the target.
These possibilities give even more flexibility to the mechanism because they mean that an operation that needs agents with certain arguments open doesn't care whether they come from an argument or an operand of the original routine. This is particularly useful for iterators and means that if you have two lists
<code>
your_account_list: LIST [ACCOUNT]
your_integer_list: LIST [INTEGER]
</code>
you may write both
<code>
your_account_list.do_all (agent {ACCOUNT}.deposit_one_grand)
your_integer_list.do_all (agent add_to_total)
</code>
even though the two procedures used in the agents have quite different forms. We are assuming here that the first one, a feature of class <code>ACCOUNT</code>, is something like
<code>
deposit_one_grand
-- Deposit one thousand into `Current'.
do
deposit (1000)
end
</code>
The procedure <code>deposit_one_grand</code> takes no arguments. In the <code>do_all</code> example above, its target is open. The target will be, in turn, each instance of <code>ACCOUNT</code> in <code>your_account_list</code>.
In contrast, the other routine, assumed to be a feature of the calling class, does take an argument <code>x</code>:
<code>
add_to_total (x: INTEGER)
-- Add `x' to the value of `total'.
do
total := total + x
end
</code>
Here, <code>total</code> is assumed to be an integer attribute of the enclosing class. In the <code>do_all</code> example, each instance of <code>your_integer_list</code> will fill the argument <code>x</code> left open in <code>add_to_total</code>.
Without the versatility of playing with open and closed arguments for both the original arguments and target, you would have to write separate iteration mechanisms for these two cases. Here you can use a single iteration routine of <code>LIST</code> and similar classes of EiffelBase, <code>do_all</code>, for both purposes: <br/>
* Depositing money on every account in a list of accounts.
* Adding all the integers in a list of integers.
==Inline agents==
In the agent discussion above, it has been assumed that there already exists some routine that we wish to represent with an agent. However, sometimes the only usage of such a routine could be as an agent ... that is, the routine does not make sense as a feature of the class in question. In these cases, we can use '''inline agents'''. With an inline agent we write the routine within the agent declaration.
If we consider the use of agents instead of class features in the two <code>do_all</code> examples in the previous section, the agents would be coded as follows:
<code>
your_account_list.do_all
(agent (a: ACCOUNT)
do
a.deposit (1000)
end)
</code>
and
<code>
your_integer_list.do_all
(agent (i: INTEGER)
do
total := total + i
end)
</code>
The syntax of the inline agent corresponds to the syntax of a routine. Immediately following the <code>agent</code> keyword are the formal arguments and in the case of functions the type for <code>Result</code>. Inline agents can have <code>local</code> entities, preconditions, and postconditions, just like any routine.
Inline agents do not have access to the local entities of the routine in which they are coded. So, if it is necessary to use the routine's local variables, they must be passed as arguments to the inline agent.
Here's an example of an inline agent which is a function. It is used in the context of a check to see if every element of <code>your_integer_list</code> is positive:
<code>
your_integer_list.for_all
(agent (i: INTEGER): BOOLEAN
do
Result := (i > 0)
ensure
definition: Result = (i > 0)
end)
</code>
Inline agents are interesting also as an implementation of the notion of [http://en.wikipedia.org/wiki/Closure_(computer_science) closures] in computer science.
Agents provide a welcome complement to the other mechanisms of Eiffel. They do not conflict with them but, when appropriate -- as in the examples sketched in this section -- provide clear and expressive programming schemes, superior to the alternatives.
{{SeeAlso|[[Event Programming with Agents]] }}

View File

@@ -0,0 +1,337 @@
[[Property:title|ET: Design by Contract (tm), Assertions and Exceptions]]
[[Property:weight|-8]]
[[Property:uuid|2ef367c9-34d9-d45e-a722-163b39581405]]
Eiffel directly implements the ideas of Design by Contract&#153; , which enhance software reliability and provide a sound basis for software specification, documentation and testing, as well as exception handling and the proper use of inheritance.
==Design by Contract&#153; basics==
A system -- a software system in particular, but the ideas are more general -- is made of a number of cooperating components. Design by Contract&#153; states that their cooperation should be based on precise specifications -- contracts -- describing each party's expectations and guarantees.
An Eiffel contract is similar to a real-life contract between two people or two companies, which it is convenient to express in the form of tables listing the expectations and guarantees. Here for example is how we could sketch the contract between a homeowner and the telephone company:
{| border="1"
|-
| style="width=10%" |provide telephone service
| style="width=35%" |'''OBLIGATIONS'''
| style="width=35%" |'''BENEFITS'''
|-
| '''Client'''
| (Satisfy precondition:) <br/>
Pay bill.
| (From postcondition:) <br/>
Receive telephone service from Supplier.
|-
| '''Supplier'''
| (Satisfy precondition:) <br/>
Provide telephone service.
| (From postcondition:) <br/>
No need to provide anything if bill not paid.
|}
Note how the obligation for each of the parties maps onto a benefit for the other. This will be a general pattern.
The client's obligation, which protects the supplier, is called a '''precondition'''. It states what the client must satisfy before requesting a certain service. The client's benefit, which describes what the supplier must do (assuming the precondition was satisfied), is called a '''postcondition'''.
In addition to preconditions and postconditions, contract clauses include '''class invariants''', which apply to a class as a whole. More precisely a class invariant must be ensured by every creation procedure (or by the default initialization if there is no creation procedure), and maintained by every exported routine of the class.
==Expressing assertions==
Eiffel provides syntax for expressing preconditions (<code>require</code>), postconditions (<code>ensure</code>) and class invariants (<code>invariant</code>), as well as other assertion constructs studied later (see "[[ET: Instructions|Instructions]]" ): loop invariants and variants, check instructions.
Here is a partial update of class <code>ACCOUNT</code> with more assertions:
<code>
note
description: "Simple bank accounts"
class
ACCOUNT
feature -- Access
balance: INTEGER
-- Current balance
deposit_count: INTEGER
-- Number of deposits made since opening
do
... As before ...
end
feature -- Element change
deposit (sum: INTEGER)
-- Add `sum' to account.
require
non_negative: sum >= 0
do
... As before ...
ensure
one_more_deposit: deposit_count = old deposit_count + 1
updated: balance = old balance + sum
end
feature {NONE} -- Implementation
all_deposits: DEPOSIT_LIST
-- List of deposits since account's opening.
invariant
consistent_balance: (all_deposits /= Void) implies
(balance = all_deposits . total)
zero_if_no_deposits: (all_deposits = Void) implies
(balance = 0)
end -- class ACCOUNT
</code>
Each assertion is made of one or more subclauses, each of them a boolean expression (with the additional possibility of the <code>old</code> construct). The effect of including more than one sub clause, as in the postcondition of <code>deposit</code> and in the invariant, is the same as connecting them through an <code>and</code>. Each clause may be preceded by a label, such as <code>consistent_balance</code> in the invariant, and a colon; the label is optional and does not affect the assertion's semantics, except for error reporting as explained in the next section, but including it systematically is part of the recommended style. The value of the boolean expression <code>a implies b</code> is true except if <code>a</code> is true and <code>b</code> false.
Because assertions benefit from the full power of boolean expressions, they may include function calls. This makes it possible to express sophisticated consistency conditions, such as " the graph contains no cycle", which would not be otherwise expressible through simple expressions, or even through first-order predicate calculus, but which are easy to implement as Eiffel functions returning boolean results.
===Preconditions===
The precondition of a routine expresses conditions that the routine is imposing on its clients. Here a call to <code>deposit</code> is correct if and only if the value of the argument is non-negative. The routine does not guarantee anything for a call that does not satisfy the precondition. It is in fact part of the Eiffel method that a routine body should '''never''' test for the precondition, since it is the client's responsibility to ensure it. (An apparent paradox of Design by Contract&#153;, which is reflected in the bottom-right entries of the preceding and following contract tables, and should not be a paradox any more at the end of this discussion, is that one can get more reliable software by having fewer explicit checks in the software text.)
===Postconditions===
The postcondition of a routine expresses what the routine guaranteed to its clients for calls satisfying the precondition. The notation <code>old expression</code>, valid in postconditions ( <code>ensure</code> clauses) only, denotes the value that <code>expression</code> had on entry to the routine.
The precondition and postcondition state the terms of the contract between the routine and its clients, similar to the earlier example of a human contract:
{| border="1"
|-
| style="width=10%" |<code>deposit</code>
| style="width=35%"| '''OBLIGATIONS'''
| style="width=35%" | '''BENEFITS'''
|-
| '''Client'''
| (Satisfy precondition:) <br/>
Use a non-negative argument.
| (From postcondition:) <br/>
Get deposits list and balance updated.
|-
| '''Supplier'''
| (Satisfy precondition:) <br/>
Update deposits list and balance.
| (From postcondition:) <br/>
No need to handle negative arguments.
|}
===Class invariants===
The class invariant, as noted, applies to all features. It must be satisfied on exit by any creation procedure, and is implicitly added to both the precondition and postcondition of every exported routine. In this respect it is both good news and bad news for the routine implementer: good news because it guarantees that the object will initially be in a stable state, averting the need in the example to check that the total of <code>all_deposits</code> is compatible with the <code>balance</code>; bad news because, in addition to its official contract as expressed by its specific postcondition, every routine must take care of restoring the invariant on exit.
A requirement on meaningful contracts is that they should be in good faith: satisfiable by an honest partner. This implies a consistency rule: if a routine is exported to a client (either generally or selectively), any feature appearing in its precondition must also be available to that client. Otherwise -- for example if the precondition included <code>require n > 0</code>, where <code>n</code> is a secret attribute -- the supplier would be making demands that a good-faith client cannot possibly check for.
Note in this respect that guaranteeing a precondition does not necessarily mean, for the client, testing for it. Assuming <code>n</code> is exported, a call may test for the precondition
<code>
if x.n > 0 then
x.r
end
</code>
possibly with an <code>else</code> part. But if the context of the call, in the client's code, implies that <code>n</code> is positive -- perhaps because some preceding call set it to the sum of two squares -- then there is no need for an <code>if</code> or similar construct.
{{note|In such a case, a <code>check</code> instruction as introduced later ( "[[ET: Instructions|Instructions]]" ) is recommended if the reason for omitting the test is non-trivial. }}
==Using contracts for built-in reliability==
What are contracts good for? Their first use is purely methodological. By applying a discipline of expressing, as precisely as possible, the logical assumptions behind software elements, you can write software whose reliability is built-in: software that is developed hand-in-hand with the rationale for its correctness.
This simple observation -- usually not clear to people until they have practiced Design by Contract&#153; thoroughly on a large-scale project -- brings as much change to software practices and quality as the rest of object technology.
==Run-time assertion monitoring==
Contracts in Eiffel are not just wishful thinking. They can be monitored at run time under the control of compilation options.
It should be clear from the preceding discussion that contracts are not a mechanism to test for special conditions, for example erroneous user input. For that purpose, the usual control structures ( <code>if deposit_sum > 0 then</code> ...) are available, complemented in applicable cases by the exception handling mechanism reviewed next. An assertion is instead a '''correctness condition''' governing the relationship between two software modules (not a software module and a human, or a software module and an external device). If <code>sum</code> is negative on entry to <code>deposit</code>, violating the precondition, the culprit is some other software element, whose author was not careful enough to observe the terms of the deal. Bluntly:
{{rule|name=Assertion Violation|text=A run-time assertion violation is the manifestation of a bug. }}
To be more precise: <br/>
* A precondition violation signals a bug in the client, which did not observe its part of the deal.
* A postcondition (or invariant) violation signals a bug in the supplier -- the routine -- which did not do its job.
That violations indicate bugs explains why it is legitimate to enable or disable assertion monitoring through mere compilation options: for a correct system -- one without bugs -- assertions will always hold, so the compilation option makes no difference to the semantics of the system.
But of course for an incorrect system the best way to find out where the bug is -- or just that there is a bug -- is often to monitor the assertions during development and testing. Hence the presence of the compilation options, which EiffelStudio lets you set separately for each class, with defaults at the system and cluster levels: <br/>
* <code>no</code> : assertions have no run-time effect.
* <code>require</code> : monitor preconditions only, on routine entry.
* <code>ensure</code> : preconditions on entry, postconditions on exit.
* <code>invariant</code> : same as <code>ensure</code>, plus class invariant on both entry and exit for qualified calls.
* <code>all</code> : same as <code>invariant</code>, plus <code>check</code> instructions, loop invariants and loop variants.
An assertion violation, if detected at run time under one of these options other than the first, will cause an exception ( [[ET: Design by Contract (tm), Assertions and Exceptions#exception_handling|"Exception handling"]] ). Unless the software has an explicit "retry" plan as explained in the discussion of exceptions, the violation will produce an exception trace and cause termination (or, in EiffelStudio, a return to the environment's browsing and debugging facilities at the point of failure). If present, the label of the violated sub clause will be displayed, to help identify the problem.
The default is <code>require</code>. This is particularly interesting in connection with the Eiffel method's insistence on reuse: with libraries such as EiffelBase, richly equipped with preconditions expressing terms of use, an error in the '''client software''' will often lead, for example through an incorrect argument, to violating one of these preconditions. A somewhat paradoxical consequence is that even an application developer who does not apply the method too well (out of carelessness, haste, indifference or ignorance) will still benefit from the presence of contracts in someone else's library code.
During development and testing, assertion monitoring should be turned on at the highest possible level. Combined with static typing and the immediate feedback of compilation techniques such as the Melting Ice Technology, this permits the development process mentioned in the section [[ET: The Software Process in Eiffel#Quality_and_functionality|"Quality and functionality"]], where errors are exterminated at birth. No one who has not practiced the method in a real project can imagine how many mistakes are found in this way; surprisingly often, a violation will turn out to affect an assertion that was just included for goodness' sake, the developer being convinced that it could never "possibly" fail to be satisfied.
By providing a precise reference (the description of what the software is supposed to do) against which to assess the reality (what the software actually does), Design by Contract&#153; profoundly transforms the activities of debugging, testing and quality assurance.
When releasing the final version of a system, it is usually appropriate to turn off assertion monitoring, or bring it down to the <code>require</code> level. The exact policy depends on the circumstances; it is a trade off between efficiency considerations, the potential cost of mistakes, and how much the developers and quality assurance team trust the product. When developing the software, however, you should always assume -- to avoid loosening your guard -- that in the end monitoring will be turned off.
==The contract form of a class==
Another application of assertions governs documentation. Environment mechanisms, such as clicking the <code>Form Contract</code> icon in Eiffelstudio, will produce, from a class text, an abstracted version which only includes the information relevant for client authors. Here is the contract form of class <code>ACCOUNT</code> in the latest version given:
<code>
note
description: "Simple bank accounts"
class interface
ACCOUNT
feature -- Access
balance: INTEGER
-- Current balance
deposit_count: INTEGER
-- Number of deposits made since opening
feature -- Element change
deposit (sum: INTEGER)
-- Add `sum' to account.
require
non_negative: sum >= 0
ensure
one_more_deposit: deposit_count = old deposit_count + 1
updated: balance = old balance + sum
invariant
consistent_balance: balance = all_deposits.total
end -- class interface ACCOUNT
</code>
The words <code>class interface</code> are used instead of just <code>class</code> to avoid any confusion with actual Eiffel text, since this is documentation, not executable software. (It is in fact possible to generate a compilable variant of the Contract Form in the form of a deferred class, a notion defined later.)
Compared to the full text, the Contract Form of a class (also called its "short form") retains all its interface properties, relevant to client authors: <br/>
* Names and signatures (argument and result type information) for exported features.
* Header comments of these features, which carry informal descriptions of their purpose. (Hence the importance, mentioned in "[[ET: Hello World|Hello World]]", of always including such comments and writing them carefully.)
* Preconditions and postconditions of these features (at least the subclauses involving only exported features).
* Class invariant (same observation).
The following elements, however, are not in the Contract Form: any information about non-exported features; all the routine bodies (<code>do</code> clauses, or the <code>external</code> and <code>once</code> variants seen in [[ET: The Static Picture: System Organization#External_software|"External software"]] above and [[ET: Other Mechanisms#Once_routines_and_shared_objects|"Once routines and shared objects"]] below); assertion subclauses involving non-exported features; and some keywords not useful in the documentation.
In accordance with the Uniform Access principle (described in [[ET: The Dynamic Structure: Execution Model|"Objects, fields, values, and references"]] ), the Contract Form does not distinguish between attributes and argument-less queries. In the above example, <code>balance</code> could be one or the other, as it makes no difference to clients, except possibly for performance.
The Contract Form is the fundamental tool for using supplier classes in the Eiffel method. It enables client authors to reuse software elements without having to read their source code. This is a crucial requirement in large-scale industrial developments.
The Contract Form satisfies two key requirements of good software documentation: <br/>
* It is truly abstract, free from the implementation details of what it describes and concentrating instead on its functionality.
* Rather than being developed separately -- an unrealistic requirement, hard to impose on developers initially and becoming impossible in practice if we expect the documentation to remain up to date as the software evolves -- the documentation is extracted from the software itself. It is not a separate product but a different view of the same product. This prolongs the '''Single Product''' principle that lies at the basis of Eiffel's seamless development model (shown in [[ET: The Software Process in Eiffel|The Software Process in Eiffel]] ).
The Contract Form is only one of the relevant views. EiffelStudio, for example, generates graphical representations of system structures, to show classes and their relations -- client, inheritance -- according to the conventions of BON (the Business Object Notation). In accordance with the principles of seamlessness and reversibility, EiffelStudio lets you both work on the text, producing the graphics on the fly, or work on the graphics, updating the text on the fly; you can alternate as you wish between these two modes. The resulting process is quite different from more traditional approaches based on separate tools: an analysis and CASE workbench, often based on UML, to deal with an initial "bubble-and-arrow" description; and a separate programming environment, to deal with implementation aspects only. In Eiffel the environment provides consistent, seamless support from beginning to end.
The Contract Form -- or its variant the Flat-Contract Form, which takes account of inheritance ( [[ET: Inheritance#Flat_and_Flat-Contract_Forms|"Flat and Flat-Contract Forms"]] ) are the standard form of library documentation, used extensively, for example, in the book <span> [http://www.eiffel.com/services/training/books.html Reusable Software] </span> (see bibliography). Assertions play a central role in such documentation by expressing the terms of the contract. As demonstrated a contrario by the widely publicized $500-million crash of the Ariane-5 rocket launcher in June of 1996, due to the incorrect reuse of a software module from the Ariane-4 project, '''reuse without a contract documentation''' is the path to disaster. Non-reuse would, in fact, be preferable.
==Exception handling==
Another application of Design by Contract&#153; governs the handling of unexpected cases. The vagueness of many discussions of this topic follows from the lack of a precise definition of terms such as "exception". With Design by Contract&#153; we are in a position to be specific: <br/>
* Any routine has a contract to achieve.
* Its body defines a strategy to achieve it -- a sequence of operations, or some other control structure involving operations. Some of these operations are calls to routines, with their own contracts; but even an atomic operation, such as the computation of an arithmetic operation, has an implicit contract, stating that the result will be representable.
* Any one of these operations may <code>fail</code>, that is to say be unable to meet its contract; for example an arithmetic operation may produce an overflow (a non-representable result).
* The failure of an operation is an '''exception''' for the routine that needed the operation.
* As a result the routine may fail too -- causing an exception in its own caller.
Note the precise definitions of the two key concepts, failure and exception. Although failure is the more basic one -- since it is defined for atomic, non-routine operations -- the definitions are mutually recursive, since an exception may cause a failure of the recipient routine, and a routine's failure causes an exception in its own caller.
Why state that an exception "may" cause a failure? It is indeed possible to "rescue" a routine from failure in the case of an exception, by equipping it with a clause labeled <code>rescue</code>, as in:
<code>
read_next_character (f: FILE)
-- Make next character available in last_character.
-- If impossible, set failed to True.
require
readable: file.readable
local
impossible: BOOLEAN
do
if impossible then
failed := True
else
last_character := low_level_read_function (f)
end
rescue
impossible := True
retry
end
</code>
This example includes the only two constructs needed for exception handling: <code>rescue</code> and <code>retry</code>. A <code>retry</code> instruction is only permitted in a rescue clause; its effect is to start again the execution of the routine, without repeating the initialization of local entities (such as <code>impossible</code> in the example, which was initialized to <code>False</code> on first entry). Features <code>failed</code> and <code>last_character</code> are assumed to be attributes of the enclosing class.
This example is typical of the use of exceptions: as a last resort, for situations that should not occur. The routine has a precondition, <code>file.readable</code>, which ascertains that the file exists and is accessible for reading characters. So clients should check that everything is fine before calling the routine. Although this check is almost always a guarantee of success, a rare combination of circumstances could cause a change of file status (because a user or some other system is manipulating the file) between the check for <code>readable</code> and the call to <code>low_level_read_function</code>. If we assume this latter function will fail if the file is not readable, we must catch the exception.
A variant would be
<code>
local
attempts: INTEGER
do
if attempts < Max_attempts then
last_character := low_level_read_function (f)
else
failed := True
end
rescue
attempts := attempts + 1
retry
end
</code>
which would try again up to <code>Max_attempts</code> times before giving up.
The above routine, in either variant, never fails: it always fulfills its contract, which states that it should either read a character or set <code>failed</code> to record its inability to do so. In contrast, consider the new variant
<code>
local
attempts: INTEGER
do
last_character := low_level_read_function (f)
rescue
attempts := attempts + 1
if attempts < Max_attempts then
retry
end
end
</code>
with no more role for <code>failed</code>. In this case, after <code>Max_attempts</code> unsuccessful attempts, the routine will execute its <code>rescue</code> clause to the end, with no <code>retry</code> (the <code>if</code> having no <code>else</code> clause). This is how a routine '''fails'''. It will, as noted, pass on the exception to its caller.
Such a rescue clause should, before terminating, restore the invariant of the class so that the caller and possible subsequent <code>retry</code>attempts from higher up find the objects in a consistent state. As a result, the rule for an absent <code>rescue</code> clause -- the case for the vast majority of routines in most systems -- is that it is equivalent to
<code>
rescue
default_rescue
</code>
where procedure <code>default_rescue</code> comes from <code>ANY</code>, where it is defined to do nothing; in a system built for robustness, classes subject to non-explicitly-rescued exceptions should redefine <code>default_rescue</code> (perhaps using a creation procedure, which is bound by the same formal requirement) so that it will always restore the invariant.
Behind Eiffel's exception handling scheme lies the principle -- at first an apparent platitude, but violated by many existing mechanisms -- that a routine should '''either succeed or fail'''. This is in turn a consequence of Design by Contract&#153; principles: succeeding means being able to fulfill the contract, possibly after one or more <code>retry</code>; failure is the other case, which must always trigger an exception in the caller. Otherwise it would be possible for a routine to miss its contract and yet return to its caller in a seemingly normal state. That is the worst possible way to handle an exception.
Concretely, exceptions may result from the following events: <br/>
* A routine failure ( <code>rescue</code> clause executed to the end with no <code>retry</code>), as just seen.
* Assertion violation, if for a system that runs with assertion monitoring on.
* Attempt to call a feature on a void reference: <code>x.f (...)</code>, the fundamental computational mechanism, can only work if <code>x</code> is attached to an object, and will cause an exception otherwise.
* Developer exception, as seen next.
* Operating system signal:arithmetic overfolow; no memory available for a requested creation or twin -- even after garbage collection has rummaged everything to find some space. (But no C/C++-like "wrong pointer address", which cannot occur thanks to the statically typed nature of Eiffel.)
It is sometimes useful, when handling exceptions in <code>rescue</code> clauses, to ascertain the exact nature of the exception that got the execution there. For this it is suffices to inherit from the Kernel Library class <code>EXCEPTIONS</code>, which provides queries such as <code>exception</code>, giving the code for the last exception, and symbolic names ( [[ET: Other Mechanisms#Constant_attributes|"Constant attributes"]] ) for all such codes, such as <code>No_more_memory</code>. You can then process different exceptions differently by testing <code>exception</code> against various possibilities. The method strongly suggests, however, that exception handling code should remain simple; a complicated algorithm in a <code>rescue</code> clause is usually a sign that the mechanism is being misused. Class <code>EXCEPTIONS</code> also provides various facilities for fine-tuning the exception facilities, such as a procedure <code>raise</code> that will explicitly trigger a "developer exception" with a code that can then be detected and processed. Exception handling helps produce Eiffel software that is not just correct but robust, by planning for cases that should not normally arise, but might out of Murphy's law, and ensuring they do not affect the software's basic safety and simplicity.
==Other applications of Design by Contract&#153;==
The Design by Contract&#153; ideas pervade the Eiffel method. In addition to the applications just mentioned, they have two particularly important consequences: <br/>
* They make it possible to use Eiffel for analysis and design. At a high level of abstraction, it is necessary to be precise too. With the exception of BON, object-oriented analysis and design methods tend to favor abstraction over precision. Thanks to assertions, it is possible to express precise properties of a system ("At what speed should the alarm start sounding?") without making any commitment to implementation. The discussion of deferred classes ( [[ET: Inheritance#Applications_of_deferred_classes|"Applications of deferred classes"]] ) will show how to write a purely descriptive, non-software model in Eiffel, using contracts to describe the essential properties of a system without any computer or software aspect.
* Assertions also serve to control the power of inheritance-related mechanisms -- redeclaration, polymorphism, dynamic binding -- and channel them to correct uses by assigning the proper semantic limits. See [[ET: Inheritance#Inheritance_and_contracts|"Inheritance and contracts"]] .

Some files were not shown because too many files have changed in this diff Show More