-- Geoff (14 Jun 99): This documentation is out of date in parts .. -- Following the Beta release matching SmallEiffel -0.78, I will -- update this documentation to reflect the current distribution -- of elj-win32. =============================================================================== elj-win32: A win32 compatible SmallEiffel Distribution Home Page: http://www.elj.com/elj-win32/ This file can found at http://www.elj.com/elj-win32/elj-win32-readme.txt Eiffel Liberty Journal http://www.elj.com/ Geoff Eldridge geoff@elj.com Version: 0.4 (14 Jun 99) Table of Contents ----------------- 1. Introduction 1.1 What is Eiffel? 1.2 Eiffel: Getting Started 1.3 SmallEiffel: The Past, Present and Future 1.4 Why elj-win32 ? 2. Download and Install elj-win32 -- 2.1 Download SmallEiffel: The GNU Eiffel Compiler -- 2.2 Download lcc-win32: A free Compiler System for Windows -- 2.3 Download elj-win32: The files to generate SE binaries -- 2.4 Install SmallEiffel: The GNU Eiffel Compiler -- 2.5 Install lcc-win32: A free Compiler System for Windows -- 2.6 Generate SmallEiffel Binaries and Configure 2.7 Download UltraEdit: A shareware Win32 Editor (optional) 2.8 Install UltraEdit: A shareware Win32 Editor (optional) 2.9 AUTOEXEC.BAT Example File 2.10 Test Installation 2.11 Standard Classes Distributed with SmallEiffel 3. SmallEiffel Example Programs 3.1 P_RANDOM_TEST 3.2 sqrt function using .. 3.3 GRAPE (A win32 GUI for Eiffel) -- lcc-win32 Supplmentary Documentation -- extracts from the lcc-win32 documentation Appendix 1 - lcc : The Compiler Appendix 2 - lcclnk : The Linker Appendix 3 - lcclib : The librarian Appendix 4 - lcc-win32 Designer's (Jacob Navia) Introduction ------------------------------------------------------------------------------- 1. Introduction ============ -- goto step 2 if you are in a hurry.. 1.1 What is Eiffel? --------------- Eiffel is an advanced object-oriented programming language that emphasizes the design and construction of high-quality and reusable software. Eiffel is not a superset or extension of any other language. Eiffel strongly encourages OO programming and does not allow dangerous practices from previous generation languages although it does interface to other languages such as C and C++. Eiffel supports the concept of "Design by Contract" to improve software correctness. Beyond the language aspect Eiffel may be viewed as a method of software construction. Eiffel is an excellent vehicle for software education, including for a first programming course. Eiffel was created by Bertrand Meyer and developed by his company, Interactive Software Engineering (ISE) of Goleta, CA. Dr. Meyer borrowed on his extensive experience with OOP, particularly with Simula. He also added in important concepts from his academic work on software verification and computer language definition. Eiffel's design addresses many practical concerns that software engineers face when creating complex software. Eiffel has evolved continually since its conception on September 14, 1985 and its first introduction in 1986. Eiffel is named after Gustave Eiffel, the engineer who designed the Eiffel Tower. A copy of the Eiffel FAQ can be found at: http://www.elj.com/eiffel/faq/ 1.2 Eiffel: Getting Started ----------------------- An `Eiffel: Getting Started' web page is available from: http://www.elj.com/eiffel/getting-started/ In particular you are encouraged to read: * ``Eiffel: An Invitation'' by Bertrand Meyer http://www.eiffel.com/doc/manuals/language/intro/ an online copy of the first chapter of ``Eiffel: The Language'' * `Eiffel: An Advanced Introduction'' by Alan Snyder and Brian Vetter http://www.elj.com/eiffel/intro/ An 89 page Eiffel introduction in html/pdf/ps formats available from: 1.3 SmallEiffel: The Past, Present and Future ----------------------------------------- -- incomplete -- needs more work .. Eiffel is a remarkably versatile object-oriented programming language and method. Eiffel has always been admired for its elegant and carefully crafted design. However, it has been perceived as either been too academic or confined to niche applications, like rapidly evolving financial trading systems, etc. The SmallEiffel project has delivered to the Eiffel community a free compiler and in early in 1998 it officially became the GNU Eiffel compiler. SmallEiffel as of version -0.78 (Jun 1999) is fully functional Eiffel compiler and tools and it has a garbage collection and exception handling It is is a `no frills' compiler that is easy to learn and use. It also provides free access to Eiffel development environment which Eiffel users New and Old can get a feel for the Eiffel Language and Method before exploring the excellent commercial versions of Eiffel. SmallEiffel ``Edit-Compile-Test'' cycle times are stunningly quick, even for large programs, and can compete with the best of the latest scripting languages (Perl and Python). The benefit of Small Eiffel compiler in comparison to the current scripting language technologies is the resulting application executable and the fast application processing times. SmallEiffel seems an obvious candidate to perform many of the web-initiated CGI functions currently being performed by Perl and Python. For this to occur a number of libraries are required (at a bare minimum a ``regular expression' and `sockets' library. Commercial versions of these libraries are available across the vendor distributions and are not currently available to SmallEiffel. This situation may change in the future, however in the meantime we can draw much inspiration and insight from our Python colleagues who have already developed excellent Python interfaces to regexp and socket libraries. Even though this distribution has been targetted for the WinTel win32 platform, much of the Eiffel code developed on other platforms can be used no change. It is hoped with time that a win32 GUI library will become available to the elj-win32 SmallEiffel distribution. 1.4 Why elj-win32 ? --------------- This ``SmallEiffel: The GNU Eiffel Compiler'' distribution has been put together by the ``Eiffel Liberty Journal'' (elj) and we hope you find it useful. This distribution has been put together after 2 years of half-hearted attempts by the author to install SmallEiffel on a WinTel platform. The obvious choice as a win32 compiler is the cyngus gcc compiler. However, there was always a subtle compile option required or environment variable tweek that I did not know about. As a result I avoided SmallEiffel and I am sure I am not alone on this. Things changed quickly in late May following a Roger Browne suggestion that about the lcc-win32 compiler. I quickly had a free C compiler generating the SmallEiffel binaries and a compiler that was happy on win32. Anyway, the Home Page for the `elj-win32' Distribution is: http://www.elj.com/elj-win32/ There is also an `elj-win32-discuss' email discussion Group at: . to subscribe send an email to: elj-win32-discuss-subscribe@makelist.com . http://www.findmail.com/list/noframes/elj-win32-discuss/info.html If you have any comments, feedback, etc, please contact Geoff Eldridge ( geoff@elj.com ) The ``Eiffel Liberty Journal'' has been created to expose the Eiffel Language and Method to a broader audience. The Home Page is at: http://www.elj.com/ and regular (almost daily) updates are advised on the `What's New' page at: http://www.elj.com/new/ We hope you visit often and in particular we encourage your contributions. Again contact Geoff Eldridge (geoff@elj.com). 2. Download and Install the elj-win32 distrubution =============================================== -- much of this section has been replaced by the automatic setup utility. -- We have left it here for you information as it basically describes the -- steps performed automatically. 2.1 Download SmallEiffel: The GNU Eiffel Compiler --------------------------------------------- * Goto the SmallEiffel Home Page: http://smalleiffel.loria.fr/ Acquaintant yourself with the contents. There are links to numerous resources including a FAQ, Documentation, etc. * Download the SmallEiffel source (approximately 1.6 MB) from: http://smalleiffel.loria.fr/general/download.html or the nearest mirror site to you: Australia: ftp://ftp.progsoc.uts.edu.au/pub/Eiffel/SmallEiffel/se.tgz Austria: http://gd.tuwien.ac.at/pub/languages/SmallEiffel/se.tgz USA: ftp://ftp.cs.rit.edu/pub/mirrors/SmallEiffel/se.tgz * Download `se.tgz' onto your local file system somewhere: 2.2 Download lcc-win32: A free Compiler System for Windows ------------------------------------------------------ * Goto the ``lcc-win32 Home Page'' and acquaintant yourself with the contents. There are links to numerous resources including a FAQ, Documentation, etc. http://www.cs.virginia.edu/~lcc-win32/ * Download onto your file system the latest files for: . LCC-Win32 compiler system http://www.cs.virginia.edu/~lcc-win32/lcc-win32.zip . LCC-Win32 Readme file. http://www.cs.virginia.edu/~lcc-win32/lcc/readme . Preliminary documentation (MSWord format) http://www.cs.virginia.edu/~lcc-win32/lccwin32.doc.zip . there is also a pdf version at: http://www.elj.com/elj-win32/lccwin32-doc.pdf 2.3 Download elj-win32: The files to generate SE binaries ----------------------------------------------------- * Goto the elj-win32 Home Page at: http://www.elj.com/elj-win32/ * Download the elj-win32 install BAT file `install-eljwin32.bat': http://www.elj.com/elj-win32/install-elj-win32.txt and save as: c:\SmallEiffel\misc\install-elj-win32.bat * `c:\SmallEiffel' will be the location where you will install SE in Step 2.5. 4. Install SmallEiffel: The GNU Eiffel Compiler -------------------------------------------- * Ensure Step 1 has been completed and the se.tgz is available locally to your PC. * Goto the directory you downloaded SmallEiffel into. * Unzip the se.tgz into c:\SmallEiffel . remember to check the 'Use Folder Names' * You should have the following files and directory structure: c:\SmallEiffel\ -- SmallEiffel (SE) Home directory. c:\SmallEiffel\bin\ -- where your SE binaries will -- be located c:\SmallEiffel\bin_c\ -- where SmallEiffel C files are -- located. Will be compiled by -- lcc-win32 to create the binaries -- in the above `bin\' directory. c:\SmallEiffel\contrib\ -- Files contributed by SE users. c:\SmallEiffel\COPYING -- COPYING file c:\SmallEiffel\GNU_LICENSE -- GNU Licence file c:\SmallEiffel\lib_rand\ -- a random number Eiffel example c:\SmallEiffel\lib_se\ -- a SE Eiffel Source Code. Generates -- the c files in the `bin_c\' directory. c:\SmallEiffel\lib_show\ -- lots of Eiffel examples c:\SmallEiffel\lib_std\ -- the SE kernel library class files. c:\SmallEiffel\man\ -- the man page (documentation) -- suggest printing the man pages. c:\SmallEiffel\misc\ -- Install Scripts for different -- platforms, history file, thanks c:\SmallEiffel\READ_ME -- file c:\SmallEiffel\short\ -- see man/short.txt c:\SmallEiffel\sys\ -- system.se tells SE your platform eg -- (Windows, etc) - see man\system.txt -- Also compiler, linker, loadpath files -- for your platform (eg Windows) will -- need to be set to suit your C -- environment (elj-win32 will set these -- files up for you for lcc-win32). * You must set environment variable "SmallEiffel" in your AUTEXEC.BAT to the directory in which you want to install SmallEiffel. ie set SmallEiffel=c:\smalleiffel (See the working AUTOEXEC.BAT example below.) * Append the directory: c:\smalleiffel\bin to your path in AUTOEXEC.BAT - (Again see the working AUTOEXEC.BAT example below.) 2.5 Install lcc-win32: A free Compiler System for Windows ----------------------------------------------------- * Ensure Step 2.2 has been completed and the file `se.tgz' is available locally to your PC. * Goto the directory you downloaded lcc-win32 into. * Extract the contents of lcc-win32.zip file to c:\lcc Should extract to: c:\lcc\setuplcc.exe -- Setup utility. RUN THIS FIRST. c:\lcc\ -- bin binaries c:\lcc\src -- the compiler sources c:\lcc\lib -- the import libraries c:\lcc\buildlib -- The ascii definitions for building -- all the import libraries c:\lcc\include -- the include files directory c:\lcc\weditreslib -- the run time library for c files -- generated by weditres. * Append the directory: c:\lcc\bin to your path in AUTOEXEC.BAT * Run the c:\lcc\setuplcc.exe utility lcc needs to know the location of the `include' and `lib' directories. To do this run the setuplcc utility, type both paths and exit (ie c:\lcc\include and c:\lcc\lib). This is all that is required, but it is essential. * Read the c:\lcc\readme file to acquaint yourself with the lcc distribution. * In particular, read the lcc-win32 documentation file at: http://www.cs.virginia.edu/~lcc-win32/lccwin32.doc.zip or: http://www.elj.com/elj-win32/lccwin32-doc.pdf -- should have been done as part of step 5.2 above. This is lcc-win32's authors personal documentation and provides a great insight into the win32/VC++/SDK world. I learnt an incredible amount from this documentation. There are also man page like descriptions of the lcc compiler, linker, librarian, resource editor, project builder, diff, patch, make, etc. It's just over 100 pages and should be printed out for your reference. 2.6 Generate SmallEiffel Binaries and Configure ------------------------------------------- * Step 2.3 (Install elj-win32), Step 2.5 (Install SE), Step 2.6 (Install lcc-win32) must have been successfully completed to generate the lcc-win32 SmallEiffel binaries which will reside in `c:\SmallEiffel\bin' when compiled by the lcc-win32 C compiler and linker. * run `c:\SmallEiffel\install-elj-win32.bat' from either Explorer or a DOS Shell/Console. * This should generate the following files: c:\SmallEiffel\bin\clean.exe c:\SmallEiffel\bin\compile.exe c:\SmallEiffel\bin\compile_to_jvm.exe c:\SmallEiffel\bin\compile_to_c.exe c:\SmallEiffel\bin\finder.exe c:\SmallEiffel\bin\pretty.exe c:\SmallEiffel\bin\short.exe * Alternatively, you can avoid the C compilation in this step and download the above binaries generated by elj and available from: http://www.elj.com/elj-win32/elj-win32-exe-081.zip The contents will need to unzipped locally to: c:\SmallEiffel\bin You will still need a correct installation of SmallEiffel and lcc-win32 to use these pre-compiled binaries. This step just avoids the compile/link process described in the first part of Step 2.6. 2.7 Download UltraEdit: A shareware Win32 Editor (optional) ------------------------------------------------------- * Step is optional. UltraEdit/UltraEdit-32 is a shareware program. You are limited to 45 Days of use for an unregistered version. It costs approximately $30.00 US and is certainly the best $30 I've spent on a PC application. Of course you can use your Editor of choice. I live in this editor for every thing I do my PC. It is the Editor Micrsoft, which fortuately for Ian Meade, Microsoft forgot to write. It has all the little things that it a surrogate Integrated Development Environment for the elj-win32 distribution. These include: . displays line numbers (Notepad doesn't give you line numbers), . Eiffel syntax highlighting (see below) . progect management (ie a feature which allows a user to store the filenames of files associated to the project to allow the user to quickly reference and open in the future.), . ability to run dos commands and capture resulting output to an existing or new window, . macro commands, etc. . regexp searching across multiple files, etc . smart tab setting configuration. . Column-wise editing/cutting/pasting. A page on how to use elj-win32 and UltraEdit can be found at: http://www.elj.com/eiffel/gnueiffel/ultraedit/ -- to enhanced -- add tab as delimiter .. Again you can use your favourite Editor if you don't want to pay the $30 US for this great editor. * Goto the UltraEdit Home at: http://www.ultraedit.com/ * Download one or more of the files (you have some choice) from: http://www.ultraedit.com/downloads/ I use the 32-bit version with no dictionary files which comes in as an approximate 773kB download for version 5.10A. You can also download a French version as of 5.10A. * Eiffel Syntax Highlighting Cut and paste the following code snippet into the UltraEdit file, `$ULTRAEDIT_DIR\wordfile.txt' where UltraEdit is the directory where you installed UltraEdit - in my case: c:\Program Files\ULTRAEDIT\WordFile.txt --8<-------------------------------------- $ULTRAEDIT_DIR\WordFile.txt -- /L6"Eiffel" Nocase Line Comment = -- Nocase File Extensions = e /Delimiters = ~!@$%^&*()+=|\/{}[]:;"'<> ,.?/ /C1 alias all and as check class creation debug deferred do else elseif end ensure expanded export external false feature from frozen if implies indexing infix inherit inspect invariant is like local loop not obsolete old once or prefix redefine rename require rescue retry select separate strip then true undefine unique until variant when xor /C2 BIT BOOLEAN BOOLEAN_REF CHARACTER CHARACTER_REF DOUBLE DOUBLE_REF INTEGER INTEGER_REF NONE POINTER REAL REAL_REF STRING /C3 GENERAL ANY COMPARABLE HASHABLE NUMERIC DOUBLE POINTER ARRAY STRING STD_FILES FILE STORABLE MEMORY EXCEPTIONS ARGUMENTS PLATFORM POINTER_REF -->8-------------------------------------- $ULTRAEDIT_DIR\WordFile.txt -- 2.8 Install UltraEdit: A shareware Win32 Editor (optional) ------------------------------------------------------ * Step 2.7 must have been completed. * Just a normal setup from here. 2.9 AUTOEXEC.BAT Example File ------------------------- This file is provided to show what a typical installation will do to you AUTOEXEC.BAT file: C:\PROGRA~1\MCAFEE\VIRUSS~1\SCANPM.EXE C:\ SET PATH=%PATH%;;C:\PERL\BIN;C:\PROGRA~1\ULTRAEDT;C:\LCC\BIN\;C:\SMALLEIFFEL\BIN; set smalleiffel=c:\smalleiffel 2.10 Test Installation ----------------- -- incomplete, but enough to get started. * Acquaint yourself with the SmallEiffel man pages in `c:\SmallEiffel\man'. In particular the compile, compile_to_c and short man pages. Run Example Programs: * compile -verbose -no_gc demo1.e make ^^^^^^ ^^^^^^ <- Turns the Garbage Collector off NOTE: This current distribution cannot be compiled with the new SE Garbage Collector. lcc-win32 is an ANSI compliant compiler and will not compile a lvalue expression. A bug report will be submitted to the SmallEiffel Team. It will generate a number of C files, which will then be compiled by the lcc-win32 compiler using the command in the file: c:\SmallEiffel\sys\compiler.Windows in our case this holds: lcc -O The resulting `demo1*.obj' files are then linked using the command in the file: c:\SmallEiffel\sys\linker.Windows which in our case should hold: lcclnk Check the compile man page: c:\SmallEiffel\man\compile.txt Also acquaintant your self with the file: c:\SmallEiffel\sys\loadpath.Windows which contains: .\ c:\smalleiffel\lib_std\ c:\smalleiffel\lib_rand\ c:\smalleiffel\lib_show\ c:\smalleiffel\lib_se\ c:\smalleiffel\epan\pylon\ Note: in this case it has an extra directory on top of the standard distribution. This has been edited into the `loadpath.Windows' file after the `c:\smalleiffel\epan\pylon\' directory has been created and the PYLON Class Library has been downloaded from the Eiffel Programmer's Archive Network at: http://www.elj.com/epan/archive/pylon/ 11. Standard Classes Distributed with SmallEiffel --------------------------------------------- The Standard classes located in a directory/cluster: c:\SmallEiffel\lib_std The classes are: ANY INTEGER_REF ARGUMENTS LINK ARRAY LINK2 ARRAY2 LINK2_LIST ARRAYED_COLLECTION LINKED_COLLECTION BIT_N LINK_LIST CHARACTER MEMO BIT_N_REF MEMORY BOOLEAN NATIVE_ARRAY BOOLEAN_REF NUMERIC CHARACTER_REF OUTPUT_STREAM COLLECTION PLATFORM COLLECTION2 POINTER COMPARABLE POINTER_REF COUNTER REAL DICTIONARY REAL_REF DOUBLE STD_ERROR DOUBLE_REF STD_INPUT FILE_TOOLS STD_FILE_READ FIXED_ARRAY STD_FILE_READ_WRITE FIXED_ARRAY2 STD_OUTPUT GENERAL STD_FILE_WRITE HASHABLE STD_INPUT_OUTPUT INPUT_STREAM STRING INTEGER The short form of any of class files can obtained from the `short' tool distributed with SmallEiffel. The short tool is invoked as: c:\SmallEiffel\test> short `class_name' Example: c:\SmallEiffel\test> short NUMERIC The output from the short tool can be redirected to a file. Eg.: c:\SmallEiffel\test> short NUMERIC > numeric.txt This is a great way to quickly determine the facilities offered by a class. The resulting output from the short NUMERIC command follows: deferred class interface NUMERIC -- -- This class describes a ring. -- feature(s) from HASHABLE hash_code: INTEGER ensure good_hash_value: Result >= 0 feature(s) from NUMERIC infix "+" (other: like Current): like Current -- Sum of 'Current' and 'other'. require other /= Void infix "-" (other: like Current): like Current -- Difference of 'Current' and 'other'. require other /= Void infix "*" (other: like Current): like Current -- Product of 'Current' and 'other'. require other /= Void infix "/" (other: like Current): NUMERIC -- Quotient of 'Current' and 'other'. require other /= Void; valid_divisor(other) infix "^" (exp: INTEGER): NUMERIC -- 'Current' raised to 'exp'-th power. require exp >= 0 prefix "+": like Current -- Unary plus of 'Current'. prefix "-": like Current -- Negative of 'Current'. valid_divisor (other: like Current): BOOLEAN -- Is 'other' a valid divisor for 'Current'? require other /= Void one: like Current -- The neutral element of multiplication. ensure neutral_element: -- Result is the neutral element of -- multiplication. zero: like Current -- The neutral element of addition. ensure neutral_element: -- Result is the neutral element of -- addition. sign: INTEGER infix "<" (other: like Current): BOOLEAN infix ">" (other: like Current): BOOLEAN end of deferred NUMERIC 3. SmallEiffel Example Programs ============================ 3.1 P_RANDOM_TEST ------------- * Download the Pylon Library from: http://www.elj.com/epan/archive/pylon/ * Unzip and install Pylon distribution into: c:\SmallEiffel\epan\pylon * Edit the file `c:\SmallEiffel\sys\loadpath.Windows' to include the directory `c:\smalleiffel\epan\pylon\' .\ c:\smalleiffel\lib_std\ c:\smalleiffel\lib_rand\ c:\smalleiffel\lib_show\ c:\smalleiffel\lib_se\ c:\smalleiffel\epan\pylon\ * Get the Short Form of the class P_RANDOM. Use the UltraEdit `Advanced->Dos ..' option to capture the short command output to a window or use a DOS shell and redirect the output to a file, eg. `short P_RANDOM > p_random.txt'. The output is shown below: --8<---------------------------------------------- p_random.txt -- class interface P_RANDOM -- Classic linear congruential generator verbatim from Sedgewick's Algorithms creation make (seed: INTEGER) -- Initialise pseudo-random machine from seed. feature(s) from P_RANDOM -- Initialisation make (seed: INTEGER) -- Initialise pseudo-random machine from seed. feature(s) from P_RANDOM -- Initialisation reset (seed: INTEGER) -- Initialise pseudo-random machine from seed. feature(s) from P_RANDOM -- Random number get_number (min_range, max_range: INTEGER) -- Get a new random integer inside specified range. require positive: min_range >= 0; in_order: min_range < max_range ensure inside: last_number >= min_range and last_number <= max_range; -- last_number set done: last_number: INTEGER -- Last result. end of P_RANDOM -->8---------------------------------------------- p_random.txt -- * Install the file `p_random_test.e' (see below) into a working directory `c:\SmallEiffel\temp' * type the command `compile -verbose -no_gc p_random_test.e make' * Invoke the resulting executable `p_random_test1.exe' * Check out the output.. --8<---------------------------------------------- p_random_test.e -- class P_RANDOM_TEST -- Demonstrates the PYLON randam number class. -- -- Requires the PYLON library available from: -- http://www.elj.com/epan/archive/pylon/ creation make feature -- initialisation make is -- make an array ``array'' and a random number -- generator ``random'' and test by performing -- ``perform_random_action'' and ``print_results''. do seed := 99 lower_bound := 1 upper_bound := 100 iterations := 100000 !!array.make(lower_bound, upper_bound) -- different `seed' will give different results. !!random.make(seed) perform_random_action(iterations) print_results end -- make feature -- status setting perform_random_action (l_iteration : INTEGER) is -- perform ``l_iteration'' on the random number generator -- ``random'' .. will return a random integer in the range -- ``array.lower'' and and ``array.upper''. Update the -- occurence of each number by incrementing the index of -- the array ``array'' by one require array_initialised: array /= void random_initialised: random /= void local i : INTEGER do from i := 1 until i > l_iteration loop random.get_number(array.lower, array.upper) array.put(array.item(random.last_number)+1, random.last_number) i := i + 1 end -- from i random_done := true ensure random_done: random_done end -- make feature -- status report print_results is -- display the number of occurrences of each random -- number over the iteration interval require random_done: random_done local i : INTEGER total : INTEGER do -- print each element and increment the total from i := array.lower until i > array.upper loop total := total + array.item(i) io.put_string("array.item(") io.put_integer(i) io.put_string(") = ") io.put_integer(array.item(i)) io.put_new_line i := i + 1 end -- from i -- just checking to see if it equals ``iterations'' io.put_new_line io.put_string("total iterations = ") io.put_integer(total) io.put_new_line end -- make random_done : BOOLEAN seed : INTEGER lower_bound : INTEGER upper_bound : INTEGER iterations : INTEGER feature {NONE} random : P_RANDOM array : ARRAY[INTEGER] end -- class P_RANDOM_TEST -->8---------------------------------------------- p_random_test.e -- 3.2 A Square Root Function - [Meyer 1980, 1990 - Eldridge 1996] ----------------------------------------------------------- A simple example of how Eiffel can be use in the "constructive approach to programming" is demonstrated with this simple example which shows how to develop an algorithm to compute square roots. The problem is to find a method which, given a >= 0, will yield x such that: x >= 0 and x * x = a (1) Looking at the above equation and applying a heuristic called "uncoupling" which states roughly that "one variable appearing twice may be replaced by two equal variables". Adopting this approach yields the following equation: (x >= 0) and (y >= 0) and (x * y = a) and (x = y) (2) The heuristic also states that the invariant is defined by the conjuction of the first three clauses in equation (2) is the invariant (INV) and the last one the goal (GOAL). An algorithm of the form: from establish_invariant invariant invariant_assertion -- (x >= 0) and (y >= 0) and (x*y=a) variant var -- will not be quantified in the example. until goal_assertion -- (x = y) within requried accuracy. loop -- get x and y closer to each other AND -- restore invariant end -- loop check invariant_assertion ; -- ; is the conjunction symbol goal_assertion end -- check The invariant can be established by setting x := 1 and y := a The "get x and y closer to each other" may be chosen as: x := (x + y) / 2 and the "restore invariant" may be assigned: y := a / x The references are: Meyer, B. (1980), A Basis for the Constructive Approach to Programming, in S.H. Lavington editor, Information Processing: 80, North Holland Publishing Company (1980) Meyer, B. (1991a), Introduction to the Theory of Programming Languages, Prentice Hall, 1991. Eldridge, G. (1996) Eiffel: Facilitating the Link between Software Engineering Practice and Formal Methods http://www.progsoc.uts.edu.au/~geldridg/frsd2/ This was implemented in a small elj-win32 Eiffel program and a number of test runs were conducted with full assertion checks on. See below for a copy of the source code and Eiffel output file. C:..> compile -no_gc -verbose -all_check test_sqrt.e test_sqrt The class SQRT_TEST (in file sqrt_test.e as below) -->8---------------------------------------------- sqrt_test.e -- class SQRT_TEST -- Demonstrates the Eiffel loop construct and -- the `constructive approach to programming'. creation test_sqrt feature {ANY} test_sqrt is -- test the sqrt function. local a : DOUBLE do io.put_string( "Test the sqrt function" ) io.put_new_line io.put_string( "sqrt (9) = " ) io.put_new_line io.put_double( sqrt (9) ) io.put_new_line io.put_new_line io.put_string( "sqrt (25) = " ) io.put_new_line io.put_double( sqrt (25) ) io.put_new_line io.put_new_line io.put_string( "sqrt (100) = " ) io.put_new_line io.put_double( sqrt (100) ) io.put_new_line io.put_new_line io.put_string( "sqrt (2) = " ) io.put_new_line io.put_double( sqrt (2) ) io.put_new_line io.put_new_line -- remove the comments below and compile with at -- least pre-conditions on (i.e. -require_check ). -- Pre-condition should fail -- io.put_string( "sqrt (-2) = " ) -- io.put_new_line -- io.put_double( sqrt (-2) ) -- io.put_new_line -- io.put_new_line end -- test_sqrt sqrt (a : DOUBLE) : DOUBLE is -- approximate square root of n. require a_greater_than_zero : a >= 0 local x : DOUBLE y : DOUBLE tolerance : DOUBLE do tolerance := 0.00001 -- set the tolerance from -- establish the invariant x := 1 y := a invariant (x >= 0) and (y >= 0) and (abs(x * y - a) <= tolerance) --variant -- not defined here - see text. until abs (x - y) <= tolerance loop -- get x and y closer to each other x := (x + y) / 2 -- restore the invariant y := a / x io.put_string("x = ") io.put_string(x.out) io.put_string(" and y = ") io.put_string(y.out) io.put_new_line end -- loop -- check for the desired conclusion check x >= 0 ; y >= 0 ; abs(x * y - a) <= tolerance ; abs(x - y) <= tolerance end -- check Result := x -- return the result ... end -- sqrt abs (number : DOUBLE) : DOUBLE is -- the absolute value of number do if number >= 0 then Result := number else Result := -number end -- if end -- abs end -- class SQRT_TEST -->8---------------------------------------------- sqrt_test.e -- Output From TEST_SQRT Test the sqrt function sqrt (9) = x = 5.000000 and y = 1.800000 x = 3.400000 and y = 2.647059 x = 3.023529 and y = 2.976654 x = 3.000092 and y = 2.999908 x = 3.000000 and y = 3.000000 3.000000 sqrt (25) = x = 13.000000 and y = 1.923077 x = 7.461538 and y = 3.350515 x = 5.406027 and y = 4.624468 x = 5.015248 and y = 4.984799 x = 5.000023 and y = 4.999977 x = 5.000000 and y = 5.000000 5.000000 sqrt (100) = x = 50.500000 and y = 1.980198 x = 26.240099 and y = 3.810961 x = 15.025530 and y = 6.655339 x = 10.840435 and y = 9.224722 x = 10.032579 and y = 9.967527 x = 10.000053 and y = 9.999947 x = 10.000000 and y = 10.000000 10.000000 sqrt (2) = x = 1.500000 and y = 1.333333 x = 1.416667 and y = 1.411765 x = 1.414216 and y = 1.414211 1.414216 3.3 GRAPE (A win32 GUI for Eiffel) Goto ($elj-win32)\epan\grape\examples\_simplest\ directory and look the source (more complete documentation is available from the url below). Once happy, build your first Eiffel windows excutable by running the elj.bat file in the above directory (there is one in every example directory). NB: look at the compile options in the elj.bat file and then study the man page ($elj-win32)\SmallEiffel\man\compile.txt for the compile command to gain a better understanding of what is going on. Run the resulting binary. You have run you first windows program generated by elj-win32. Repeat for the example directory titled ``_hello'' The GRAPE documentation is available from: http://www.elj.com/open-source/grape/grape-doc.pdf =============================================================================== lcc-win32 Supplmentary Documentation ==================================== The following Appendices are useful extracts taken from Jacob Navia's document titled: Lcc-Win32: A free compiler system for windows Most recent available from: http://www.cs.virginia.edu/~lcc-win32/lccwin32.doc.zip The copy of the document from which these extracts were taken is available from: http://www.elj.com/elj-win32/lccwin32-doc.pdf A detailed understanding of the following not required to get started on SmallEiffel as appropriate default settings have been made. It has been provided to allow advanced users to understand the inner workings of lcc-win32 and some of the facilities (compiler, linker, librarian) that can be adjusted by advanced SmallEiffel users in a win32 environment. Appendix 1 - lcc : The Compiler ------------------------------- Registry use of lcc Lcc creates the following key in the registry: HKEY_LOCAL_MACHINE\SOFTWARE\lcc This key contains the following subkeys: .lcc\General General type of information. .lcc\Compiler Compiler specific information .lcc\Wedit For the IDE .lcc\lcclnk For the linker .lcc\weditres For the resource editor .lcc\debug For the debugger Summary lcc-win32 command line options. Option Meaning -g Generate the debugging information. Two types of debug information will be generated: COFF and CodeView (NB09). -D Define the symbol following the 'D'. Example: -DNODEBUG The symbol NODEBUG is #defined. Note that there is NO space between the D and the symbol. -U Undefine the symbol following the 'U' -M Print in the standard output, the names of all files that the preprocessor has opened when processing the given input file. If the Fo option is active, the printing will be done in the file indicated by the Fo option. No object file is generated. -I Add a path to the includes path, i.e. to the path the compiler follows to find the header files. Example: -Ic:\project\headers Note that there is NO space between the I and the following path. -O Optimize the output. This activates the peephole optimizer. Do not use this option with the -g option above. -errout= Append the warning/error messages to the indicated file. Example errout=Myexe.err This will append to Myexe.err all warnings and error messages -eN Set the maximum error count to N. Example: -e25 The compiler will stop after 25 errors -x Generate browse information in an .xrf file -E Generate an intermediate file with the output of the preprocessor. The output file name will be deduced from the input file name, i.e. for a compilation of foo.c you will obtain foo.i -S Generate an assembly file. The output file name will be deduced from the input file name, i.e. for a compilation of foo.c you will obtain foo.asm -z Generates a file with the intermediate language of lcc. The name of the generated file will have a '.lil' extension (lcc's intermediate language) file.asm All files with an .asm extension will be supposed to be files written for lcc's assembler. Beware: the syntax of lcc's assembler is radically different from all standard assemblers.See the chapter about the assembler for more information. Appendix 2 - lcclnk : The Linker -------------------------------- The general format of a link command line is as follows: lcclnk [options] object-files library-files Default libraries: The linker will default to the following import libraries: LIBC.LIB A few C functions are in here. KERNEL32.LIB Kernel function calls COMDLG32.LIB Common dialogs library USER32.LIB Windows 'user' functions GDI32.LIB GDI functions ADVAPI32.LIB More window functions COMCTL32.LIB Library for the common controls of Win32. CRTDLL.LIB Library for the 'C' runtime functions This libraries do not need to be specified in the command line. The linker will search them anyway. To find the libraries, lcclnk uses the registry key: HKEY_LOCAL_MACHINE\SOFTWARE\lcc\lcclnk\libpath This is an ASCII_Z key, that contains the full path of the libraries directory. If the linker doesn't find this key, you will be prompted for it at the command line. If you enter a correct path, lcclnk will always use it later. The name of the object file can be an expandable file specification. For instance: '*.obj'. Options are introduced with the character '-' or the character '/'. Example: -map or /map are identical options. OPTIONS of the linker -o Sets the name of the output file to filename. Put a space between the o and the name of the file. Example: lcclnk -o myexe.exe If this option is absent, the name of the first file will be used. -subsystem Indicate the type of output file. subsystem can be one of: 1. console 2. windows If you specify console, a console application is created. The standard input, standard error, and standard output are opened. When the program is started, Windows creates automatically a console window. If you specify windows, a windowed application is created. No console window is created, and stdin, stdout, and stderr are NOT initialized. -stack-commit The default stack reserves 1MB of stack space, and commits 4096 bytes of it. With this option you can commit more pages than only one (4096 bytes). This means that a slight improvement in execution speed can be attained with programs that use a lot of stack. Example: -stack-commit 27000 -reloc This option instructs the linker to build a .reloc section. This section is a table of relocations to apply if the executable can't be loaded at its preferred load address. This option is necessary to run under Win32s. This option is automatically turned on for dlls. -dll This option indicates to the linker to produce a .dll instead of a .exe. The process of building a dll is very simple: 1. Compile the source(s) files for your dll as you compile normal sources. 2. Link the resulting object files using the option -dll and give to the linker the names of the functions exported in a .def file you include in the link. 3. Produce an import library using the implib utility. EXAMPLE lcc mylib.c lcclnk -dll mylib.obj mylib.def implib mydll.dll The format of the .def file is like this: EXPORTS Function AnotherFunction YetAnotherFunction You write the EXPORTS keyword, followed by the name of each function of the dll you want to export (i.e. to make visible for use in another executable) in a single line. -map This indicates the name of the mapfile. In the mapfile you will find the addresses of all symbols used in the link and the line number information, if available. The format for the line numbers is simple: Address:line. The address is written in 8 characters prefixed by the '0x', and the line number is written in 4 characters in decimal. This option allows you to find out where in your program a fault occurred by reading the address from the dreaded dialog box that the system displays when a program crashes. This option is not compatible with the -s option, i.e. if you ask to strip all symbols no line number information can be generated. When doing an executable with the -s option to ship to customers, it is better to do the link twice: One with the debugging information and a mapfile, and the other stripped. Do first the stripped, then the full one. The reason is that when both options -s and -map are specified, the linker writes a smaller link file without any line number information. If you do first the full link, and then the stripped, this smaller map file will overwrite the good one... Example: -map myexe.map -s This option indicates that the linker should strip all symbolic and debugging information from the executable. This means the executable can't be debugged with a debugger, but that its size will be considerably smaller. Besides, the linking speed is increased since the linker has less work to do. Use this option with debugged programs if you think those kind of things exists... -version nn.nn This option adds the version number to the executable. The numbers are the major version number and the minor version number. They are separated by a point character. Example: -version 3.8 or -version 99.01 -x Perform an analysis of the symbols that are declared 'extern' but are never referenced in any other object in the link. There are two cases: 1. The symbol is in the .text section (code section). Even if this symbol is not used in other modules, it can be used in the same module. The linker can't determine this (without disassembling the whole object file), but this can be easily checked by you: just declare the function 'static'. If it is not used, the compiler will issue a warning. 2. The symbol is in the .data or .bss section. This is a data item, and it is surely unused. Delete it from your source. errout= Write all warnings or errors to the indicated filename. No space between the equals sign and the name of the file please. Example: errout=link.err Appendix 3 - lcclib : The librarian ----------------------------------- lcclib was the last utility that was missing to complete the cycle of lcc's environment. Its task is to store several object files into one file called 'library', that contains the object files and three headers to describe to the linker what are the contents of each. The object files are stored without any modifications. No compression or other processing is required. The structure is very similar to the one used under UNIX. Usage of lcclib --------------- An option consists of an option specifier, which is either a dash ( - ) or a forward slash ( / ), followed by the name of the option. Option names cannot be abbreviated. Some options take an argument, specified after a colon (:). No spaces or tabs are allowed within an option specification. Use one or more spaces or tabs to separate option specifications on the command line. Option names and their keyword or filename arguments are not case sensitive, but identifiers used as arguments are case sensitive. lcclib processes options in the order specified on the command line and in command files. If an option is repeated with different arguments, the last one to be processed takes precedence. /VERBOSE Displays details about the progress of the session. The information is sent to standard output and can be redirected to a file. /LIST Displays information about the output library to standard output. The output can be redirected to a file. You can use /LIST to determine the contents of an existing library without modifying it. /OUT:filename Overrides the default output filename. By default, the output library is created in the current directory, with the base name of the first library or object file on the command line and the extension .LIB. /REMOVE:object Omits the specified object from the output library. LCCLIB creates an output library by first combining all objects (whether in object files or libraries), and then deleting any objects specified with /REMOVE. Lcclib source files The whole code of lcclib is a single file called appropiately lib.c. It is very small, but it implements all the machinery described above. =============================================================================== Appendix 4 - lcc-win32 Designer's (Jacob Navia) Introduction ----------------------------------------------- This adventure started in an anodine way: I went to 'Le monde en tique', the data-processing library of Paris. Wandering around, a book caught my attention: 'A retargetable C compiler: design and implementation by Christopher Fraser and David Hanson'. Mmm interesting. I took the book, started reading. A whole C compiler, neatly explained. there was even a DOS implementation. This IS interesting I told myself. I bought the book, went home, read some chapters. I was working since several years in a compiler environment project. I had written an editor 'Wedit' and sold some copies of it to fellow programmers in Paris. But my editor project was stuck: it missed the compiler. Once people bought the compiler with its integrated editor, they wouldn't think about using any other one. The editor was actually considered as an afterthought. The effort of learning a new editor was considered too big. Besides, the new programming environments were more and more closed. They were more tightly integrated, so Wedit couldn't easily start a compilation, or call the debugger. Well, it would be nice to build a whole environment... But it was a monstruous amount of work! lcc came with a compiler generating just assembler mnemonics: there was no assembler, no linker, no library, no resource compiler, no resource editor, no debugger, no header files. But then... this would be an opportunity to write an assembler, a linker and a debugger! I talked to some friends. Everyone told me I was completely crazy. But this, I knew already. So I started doing it. This was like beginning 1995 or so. It is 1997 now. The assembler is written, together with the linker, and the import librarian, the resource compiler, the resource editor, and a first version of the debugger is out. This document, as you can see in the 'stubs' (sections containing just a title) is not finished, as this project is not finished. I thought it could be useful to understand what is happening, so I include it in the project documentation. Books are dangerous. They can change people's lives. The book of Mr Fraser and Mr Hanson changed mine, and I am grateful to them for having published their work. In the process of developing the optimizer, or adjusting it to the windows environment, I have several times destroyed essential data structures of the compiler. But it has never crashed. Never. It is a solidly built piece of software, full of useful assertions, that will pinpoint exactly where you went wrong. It has a clean design, with a good separation of the front end/back end, and several functions that are really beautiful to read: take a look at 'listnodes' in dag.c for instance. [...] Quality control --------------- The following programs have been compiled with lcc. lcc 37.000 lines lcc's IDE (Wedit) 72.000 lines lcclnk 8.000 lines weditres 31.000 lines tst directory 9.000 lines Further work ------------ This is the first try of a high level optimizer. Many optimizations are still possible of course, but this release represents a compromise between the 'ideal' optimizer, that would be ready in a year or so, and the state several months ago. Within the framework of the existing register allocator,and the existing structure of lcc, some improvements can be readily be done still: . The handling of the post-increment/decrement expressions forces the usage of two registers when only one is needed in 99% of the cases. This needs a change in several functions of the front end, and in dag.c. I have attempted that change several times, but I couldn't find a stable configuration yet. . The handling of function call results uses up a register instead of using EAX directly. This needs some small changes in enode.c and expr.c, and in dag.c . The rules for assigning registers should be simplified, and the block-move / division operations should work without the contortions needed now. This will be one of the top priorities for the next months. . Now that variables are held in registers, this informations has to be written in the object file so that the debugger is aware of that. This hasn't been done yet, so the debugger will not see those variables. -------- The windows.h and the other header files A big problem were the header files. Those files make more than 4MB in modern Win32 compilers, and they are absoluteley needed for a compiler system that should run under windows. I had luck however, since the Free Software Foundation (GNU) started porting their compiler system 'gcc' to windows too, and they proposed to Scott Christley,of the net community to rewrite the windows header files. I downloaded with excitement the header files, and continued the work of Scott. I added several files, and above all tried to compress the headers as much as possible. I have worked in those header files for years, updating them, keeping them current with the newest release of the SDK I could get, and they have now nothing to do with the original files of Scott, that haven't changed for years, keeping all the bugs I corrected. Maybe this is because of the commercial interests of Cygnus Cop, the distribuitors of GNU Software, that do not see ay point in bringing a good compiler out, but in a kind of caricature of Unix they are building. If you want, you can convince for yourself by downloading several dozens of megabytes from their site http://www.cygnus.com. But let's come back to the header files. I am convinced that the compilation process now is absolutely I/O bound. With the powerful CPUs around, the disk time access overweights any other considerations. So, I thought, the best would be that the header files would be as small as possible. Normally you do not think about it when you write your header files. You write comments into them, and size considerations are far from your mind. And this is good, and should be so. The problem is, that in very big files, this adds up to a very significant portion of the compilations time, since the compiler has to parse that comment over and over again, at each compilation in fact. I took the following approach when rewriting the headers of Scott: . Eliminate all comments . Eliminate all white space and leave only what is absolutely necessary . Eliminate all redundant identifiers in function calls: for instance the function BOOL WINAPI MyWindowsApi(HWND hwnd,LPSTR name,HANDLE handleToProcess); would become: BOOL WINAPI MyWindowsApi(HWND,LPSTR,HANDLE); This allowed for a significant amount of space savings. It is true that many of the names are useful for giving you an idea of what that function does, but let's face it. lcc-win32 has no replacement for the documentation of the Win32 system, that you should buy elsewhere. Besides I think it would be very risky of deducing what the function does and what its parameters are just by looking at the documentation of it in ... a function prototype! Every effort was done to reduce the size of windows.h to its actual size, about 430K. This compares significantly better to the 4MB the compiler has to read when compiling with the header files of MSVC, and is smaller even than the characters read when you define the keyword WIN32_LEAN_AND_MEAN, that somehow reduces the size of the headers. This makes lcc a fast compiler, even if it doesn't support the precompiler header files option. I tried to follow somehow the structure of MSVC, but really, there is no close correspondence here. Just include and any special files you need. Most of them like the property sheets definitions etc are included in Windows.h, so there isn't a lot of files to include at each compilation. It is true that this contradicts somehow the objective of small size above but the problem is that re-creating that file structure would be too complicated now. Frankly I do not have the energy to do it.