PR# 2745 see message

Problem Report Summary
Submitter: cheston
Category: Compiler
Priority: Low
Date: 2001/01/31
Class: Bug
Severity: Non-critical
Number: 2745
Release: 4.5.020
Confidential: No
Status: Analyzed
Responsible:
Environment: Pentium III with Windows 98
Synopsis: see message

Description
        I have just finished writing a number of Eiffel projects.
In the process of doing this task, a number of problems were
encountered.  Some of these problems were related to differences
between the ISE, Visual Eiffel and SmallEiffel implementations of
Eiffel.  These are discussed separately.  Other problems relate
to what appear to be bugs in the ISE Eiffel system, or features
that could be designed to be more useful.  When you are moving to
a new version of Eiffel, version 5.0, this seems like the natural
time to clean up some of these difficulties.

I am currently using ISE EiffelBench version 4.5.020 on a Pentium
III with Windows 98.  I was given permission to download a beta 
version of 5.0 Eiffel.  However, I was not able to get it
running, and did not receive any assistance from a request for
help.  As a result, none of these have been tried in version 5.

I begin with two problems not previously reported.

1. For the following declaration, the error message given below
   is reported.

    node : LINKABLE [INTEGER]
    a_tuple : TUPLE [like node, like node]


-------------------------------------------------------------------------------

Error code: VTAT(1)
Error: attribute or function improperly used as anchor for `like' declaration.
What to do: make sure that anchor type is neither expanded nor itself anchored.

Class: TEST_FEATURES
Anchor name: Result
Anchor type: TUPLE [like node, like node]

-------------------------------------------------------------------------------



   Corresponding declarations in Visual Eiffel and
   SmallEiffel do not report an error.  Also, no errors occur for
            b_tuple : TUPLE [like node]

2. This problem is mentioned in the report on differences between
   the different versions of Eiffel.  It is repeated here, so that
   it does not get lost in the other standard variations.  This is
   really a problem with ISE's interpretation of the standard.  When
   ISE Eiffel reads an integer from a text file or the console, it
   also reads subsequent blanks and tabs up to and including the next
   end-of-line marker.  The client may want to know about these
   blanks, so they should not be discarded before the client has
   the chance to read them.  An example of this phenomenon is given
   at the end of this report.  Note that this behavior is
   inconsistent with Visual Eiffel and SmallEiffel.

The following problems were previously reported, but I have not
heard back so I don't know if they have been fixed or they are not
regarded as a problem.  From my perspective, they are all problems,
with some more major than others.


1. Reading numeric values from a PLAIN_TEXT_FILE and from the
    console perform differently.  It seems to me that there are
    errors in the reading of numeric values from the console. In 
    particular, if several values are placed on 
    a line of a file, file reads will obtain all the values.  
    If several values are placed on a line of input at
    the console, often only the first one is obtained.  Note that in
    the reading of characters, in both cases all the characters are
    obtained, although there is a different number of characters
    for the end of a line.  Also, when entering data at the
    console, if a line is entered which contains either blanks or
    tabs but no data, then an I/O error is often obtained.  In
    general, when reading a numeric value the Eiffel system will
    read past blanks and tabs on the first line of console 
    input to reach data on the next line entered, 
    and it will read past new lines until reaching
    a line containing something, even if the something is just a
    blank or tab.  Such a blank or tab may generate an error, i.e.
    it will not read past blanks and tabs on subsequent lines. On
    the other hand, when reading from a file, the system reads past
    an arbitrary number of blanks, tabs, and new lines to reach data.
    A project is included at the end to show this problem.

2. The function end_of_file does not seem to work with a
    RAW_FILE.  When several items are written into a RAW_FILE,
    they are placed one after the other, as would be expected.
    When they are subsequently read from the file, everything
    works properly except that end_of_file never becomes true.
    Presently we are using the file position to test for
    end of file.  While this works, it is not very clean, 
    especially when the system has a BOOLEAN function to test for 
    end of file.  This problem is also shown in the classes
    at the end of this message.

3. In the Windows system, the default location for file `output'
   in
    local outfile : PLAIN_TEXT_FILE
        do
          !!outfile.make_open_write ("output")

    is in the W_CODE directory of directory EIFGEN.  On a unix system,
    the default location is the same directory as the ace file.  They
    should be consistent.  The unix approach seems much better.
    Visual Eiffel and SmallEiffel place the output file in the
    same directory as the root class.

4. When both `and' and `and then' exist in a language, one would
    expect them to be different.  However, they seem to have identical
    affects in version 4.5.  This is also true for `or' and `or
    else'. This is a problem as a project that works
    fine in ISE Eiffel can fail in Visual Eiffel and SmallEiffel,
    as these two systems always evaluate both arguments for `and' and
    `or'.  I believe that ISE Eiffel should also do this.

5. The following features of ELKS 95 are not supported or are
    different from the ELKS specification.
    feature to_next_line of FILE
            It is also missing from PLAIN_TEXT_FILE and CONSOLE,
            but it is in STD_FILES, the type of io.
    feature fill of STRING
    feature insert_character of STRING
    feature put_substring of STRING

6. When an ARRAY of BIT 5 is declared, the system determines that
        System recompiled
        System had to be frozen to include new externals.
        Background C compilation launched.
    This is a problem for students who do not have a C
    compiler associated with Eiffel.  There is no problem for
    ARRAYs or BITs by themselves, but the combination causes the
    system to attempt to freeze the project.  This might be a side
    effect of some optimization, but it seems an abnormality.
    Also, BIT N is normally considered to be an expanded type.
    However, when in an array, it is treated as a reference type.

I would also like to mention a request:

    Presently in the PC version, the default console output is to a
    fixed sized DOS window.  Using Windows 98, I don't know how
    to get around this problem.  For students, it would be much more
    useful if the output were to a scrollable window that could
    grow to an arbitrary size.  To be useful, this would need to
    work when students only melt and do not have a C compiler
    associated with Eiffel.  If there is an easy way to fix the
    problem with the present version of Eiffel, say by some
    different Windows setting, please let me know so that I can
    use it and students in my course can use it. I would like to
    also note that this is the second most frequent complaint about
    the ISE Eiffel system.  The most frequent complaint is about
    its poor error messages. Students new to Eiffel and not very
    experienced at programming need better error messages. That
    was one of the main reasons that Eiffel was never even
    suggested when a couple years ago we switched our first year
    course from Delphi to Java.


I would really appreciate receiving feedback for these comments.

Grant Cheston
Department of Computer Science
University of Saskatchewan
Saskatoon, Sask. Canada
S7N 5A9
cheston@cs.usask.ca
To Reproduce
A class `TEST_FEATURES' is given below with creation
procedure `make'.  There is also a class OBJ used by this class,
and a data file by the name `data_file'.  In this data file,
one of the blank lines should contain several blanks and tabs,
and there should be several blanks after the 5 in the line
containing 4 and 5. 

When the project is compiled, it will generate an error for 
the line defining a_tuple.  When it is commented out, the 
project will compile and run until it generates the run-time error
        Feature: retrieved (From FILE)
        Reason: Explicit exception pending
                Code: 27 (I/O error.)
                Tag: Retrieve: unable to read type of storable.
because end of file was not detected.  If in the procedure
`test_eof_binary', the -- is removed from the second line of the
`until', then it will complete the read of the binary file
normally.  This seems to indicate an error in the feature
end_of_file.

After reading the binary file, execution will continue and then
it will pause for input.  The following lines of data
should be entered at the console (with `-' used to represent
a blank, `tab ' a tab character, and `empty' to represent
an empty line):
first line:abc
second line:defghi
third line:1----2----3
fourth line:----
fifth line:empty
sixth line:empty
seventh line:----
eight line:----tab tab 5-6-7
ninth line:----
tenth line:abc

The output as a result of reading the integers from the console
is very strange.  Also, for both the console and the binary file,
the characters obtained after the 5 do not seem correct.  Reading
from the file, the blanks after the 5 should be obtained.  Reading
from the console, the 6 and blanks around it should be obtained.


-----------------------------------------------------------------
class TEST_FEATURES

create make

feature

    make is
    local
        i, x, y : INTEGER
        c : CHARACTER
        infile : PLAIN_TEXT_FILE
    do
        x := 0; y := 1
        if x /= 0 and y/x = 1 then  -- Should yield a run-time error
        end
        if x = 0 or y/x = 1 then    -- Should yield a run-time error
        end

        test_eof_binary

        create infile.make_open_read ("..\..\test_data")
        from i := 1
        until i > 7
        loop
            infile.read_character
            io.put_string ("%NRead character " + infile.last_character.out)
            i := i + 1
        end
        infile.read_line
        from i := 1
        until i > 5
        loop
            infile.read_integer
            io.put_string ("%NRead integer " + infile.last_integer.out)
            i := i + 1
        end
        infile.read_character
        io.put_string ("%NCharacters after last read_integer" + infile.last_character.out)
        infile.read_character
        io.put_string (infile.last_character.out)
        infile.read_character
        io.put_string (infile.last_character.out)
        io.put_string ("%N")
        from i := 1
        until i > 7
        loop
            io.read_character
            io.put_string ("%NRead character " + io.last_character.out)
            i := i + 1
        end
        io.read_line
        io.put_string ("%N")
        from i := 1
        until i > 5
        loop
            io.read_integer
            io.put_string ("%NRead integer " + io.last_integer.out)
            io.put_string ("%N")
            i := i + 1
        end
        io.read_character
        io.put_string ("%NCharacters after last read_integer" + io.last_character.out)
        io.read_character
        io.put_string (io.last_character.out)
        io.read_character
        io.put_string (io.last_character.out)
        io.read_line
    end

    node : LINKABLE [INTEGER]

    a_tuple : TUPLE [like node, like node]
    b_tuple : TUPLE [like node]

    test_eof_binary is
    local
        outfile : RAW_FILE
        obj1 : OBJ
        eof_pos : INTEGER
    do
        create outfile.make_open_write ("..\..\binary_outfile")
        -- The ..\..\ occur in the preceding line for execution on a PC.
        create obj1.make(5)
        outfile.basic_store (obj1)
        create obj1.make(6)
        outfile.basic_store (obj1)
        create obj1.make(7)
        outfile.basic_store (obj1)
        eof_pos := outfile.count
        outfile.close
        io.put_string ("End of file position " + eof_pos.out + "%N")
        outfile.open_read
        from
        until outfile.end_of_file
              or outfile.position >= eof_pos
        loop
              obj1 ?= obj1.retrieved (outfile)
              io.put_string ("%N" + obj1.out)
              io.put_string ("Current position " + outfile.position.out + "%N")
        end
        io.put_string ("%NPress enter to continue execution") io.read_line
    end

end

-----------------------------------------------------------------------------
class OBJ
inherit
        STORABLE

create make

feature

        value : INTEGER

        make (i:INTEGER) is
        do
                value := i
        end

end

----------------------------------------------------------------------------
data_file contents:
-----------------------------------------------------------------
abc
defghi
1     2      3

    

            4     5         
789
10
11
12
13
14
15
---------------------------------------------------------------------------
Problem Report Interactions
From:cheston    Date:2001/01/31    Download   
State-Changed-From-To: open-analyzed
State-Changed-By: Manu
State-Changed-When: Wed Jan 31 14:06:53 PST 2001
State-Changed-Why:

Dear Grant,

Thanks for your message. I will try to answer all points in different
emails. For the moment, I would just like to discuss the issue between
and/and then and or/or else.

This is indeed the case that in ISE Eiffel and/and then and or/or else
do the exact same thing. The semantic as explained in ISE Eiffel is the
following. When you write:
- and then / or else: the compiler garantees that the second part of the
  boolean expression will be evaluated only if the first one is true in
  case of `and then', or if the first one is false in the case of
  `or else'.

- and / or have the following semantic: it is up to the compiler to
  decide in which order those expression will be evaluated at run-time.
  ETL does not specify that and/or should evaluate both left and right
  boolean expression. This is a compiler freedom for optimization.

Hope this is helpful,