Tuesday, December 20, 2011

Creation procedures

Eiffel required - a quarter of century ago - explicitly provide a creation procedure for each object; so each creation was in the form of
create my_list.make_empty
Nowadays SmartEiffel allow us to write
create my_list
when a class has put default_create command in the creation clauses list such as:
class LITTLE_LIST [ITEM]
  -- A list to contain few elements
inherit COLLECTION[ITEM]
creation default_create, make, make_empty, with_capacity
...
To create collections, lists, arrays, associative dictionaries you may use the manifest notation, like this:
some_primes := {LINKED_LIST[INTEGER] <<1, 3, 5, 7, 11, 13, 17, 23>> }
dictionary := {HASHED_DICTIONARY[CHARACTER, STRING] << 'a', "key #1";
'z', "key #2";
'z', "key #3";
'a', "key #4" >> }
bijective_dictionary :=
{HASHED_BIJECTIVE_DICTIONARY[STRING, STRING]
<< "value #1", "key #1";
"value #2", "key #2";
"value #3", "key #3" >> }
Please excuse the horrible formatting of the code, I'm working on it. 

diff "Eiffel: the language" "GNU Eiffel"

We have been asked for some informations about the differences between the language originally described in "Eiffel: the language" (1992 by Bertrand Meyer) and those accepted by the current GNU/Smart/Liberty Eiffel compiler.
Such a request is not only reasonable but requires some answer: there have been several additions and quite a few changes to the language.
The main changes are:
  1. Creation procedures
  2. agents
  3. conformance of agents 
  4. anonymous, in-lined agents (a_command(12, "Foo", agent (x: INTEGER): REAL is do Result:=x.to_real ^ 2 end )
  5. insert, also known as "non-conforming inheritance"
  6. case sensitivity
  7. inspect allow for integer intervals... 
  8. FLOAT is replaced with REAL
  9. There is no NONE (pun intended :-)
  10. other I don't recall now.
To keep things tidy I am writing a separate post for each point.

Monday, October 3, 2011

Hello World… again

The first version of the Liberty interpreter was stillborn. It took a year to utter Hello World… and never said anything more.

The second version, based on SmartEiffel, is alive and kicking, after 2 weeks gestating.
The "runner" is screaming: Hello World!

Monday, September 26, 2011

Overflow and correctness

Eiffel is a programming language that strives for correctness.
In C instead most of the times speed is regarded as more important than correctness (paraphrasing a comment of Eric Sosman ).
Most Eiffel compilers use C as an intermediate language (Liberty/SmartEiffel, ISE), so a programming language striving for correctness relies on one that trade correctness for speed.
I've been thinkering about
I think we cannot blame C as this is a issue that has no "solution"; let's see a little panoramic of the efforts poured into something "as simple" as correctness in integer calculations:
Sadly there is no magic wand for this issue.
An answer may be saturation arithmetic; digging my fading knowledge of assembler, mainly from my days on 6502 I was wondering why no one seems to use the overflow flag present in almost all CPU: it seems there is no portable way to do it access it. Oh it would be so nice to write in INTEGER_GENERAL 
«infix "+" (another: like Current): like Current is external "built_in" ensure has_overflowed=False end»
I naively thought that an arithmetic overflow would have triggered a SIGFPE signal in POSIX systems. It seems I'm wrong:
class OVERFLOW
    -- Test integer overflow
insert PLATFORM
creation make
feature make is
        local i,j: INTEGER
        do
            i := Maximum_integer
            j := i+1 -- SIGFPE expected
            ("i:=#(1), j=i+1=#(2)%N"# (&i) # (&j) ).print_on(std_output)
        end
    end
When compiled with "compile  overflow.e" Liberty Eiffel correctly says:
*** Error at Run Time ***: Require Assertion Violated.
*** Error at Run Time ***: no_overflow
3 frames in current stack.
=====  Bottom of run-time stack  =====
<system root>
Current = OVERFLOW#0x925b038
line 5 column 9 file /media/Liberty/tybor-liberty/work/tybor-sandbox/overflow.e
======================================
make OVERFLOW
Current = OVERFLOW#0x925b038
i = 2147483647
j = 0
line 9 column 4 file /media/Liberty/tybor-liberty/work/tybor-sandbox/overflow.e
======================================
infix + (infix + INTEGER_32)
Current = 2147483647
other = 1
Result = 0
line 21 column 80 file /home/paolo/current-liberty/src/lib/numeric/integral.e
=====   Top of run-time stack    =====
*** Error at Run Time ***: Require Assertion Violated.
*** Error at Run Time ***: no_overflow
but when we compile it with "compile --boost overflow.e" it happily says: "i:=2147483647, j=i+1=-2147483648" which is obviously wrong. You have to compile it with "compile --boost overflow.e --cc gcc -ftrapv" to laconically receive the answer
"Received signal 6.
Eiffel program crash at run time.
No trace when using option "-boost"
Which is not what I would expect, since signal 6 is ABRT on my system.


infix "#": Eiffel's printf

It's really nice to be able to write in Liberty/SmartEiffel:

("i:=#(1), j=i+1=#(2)%N"# (&i) # (&j) ).print_on(std_output)
("obviously foo := #(2), bar := #(1)%N" # &42 # &17).print_on(std_output)

which may look cryptic to most Eiffel programmers, but may look familiar when translated into C:
printf("i:=%d, j=i+1=%d\n", i,j)
printf("obviously foo := %d, bar := %d\n", 17,42)
Beside looking a little more convoluted it actually has quite a few advantages:
  • like QString::arg of Qt fame it allows positional arguments,
  • it does not rely on variable argument function calls,
  • it does not allocate an unnecessary array to hold the arguments; each call to # actually return a ROPE which does is an ABSTRACT_STRING holding references to two substrings; the prefix "&" operator returns a LAZY_STRING (praises to Adrian for good idea) which will not be converted to a string until it gets iterated over, usually printing or copying it.
  • it allows to write things like:
    local s,t,u: STRING
    do
    s := "Eiffel"; t:= "beautiful"
    u := s | " is a " |t| " language"
    assert (u.is_equal("Eiffel is a beautiful language")
    t.prepend("really ")
    assert (u.is_equal("Eiffel is a really beautiful language")
    -- which may also obtained with
    u := "#(1) is a #(2) language" # s # t
    end
  • it does retain type-safety (AFAIK)

Sunday, July 17, 2011

SmartEiffel as Liberty core

OK guys, I have permission from Dominique, and I guess it is better anyway.

SmartEiffel is back in the trenches. It is now completely part of LibertyEiffel.

Here is the plan:
  1. really integrate SmartEiffel into Liberty (done)
  2. separate the C backend from the AST (fix and use the acyclic visitor)
  3. remove or rewrite the Java backend (using the acyclic visitor)
  4. rewrite the interpreter as a SmartEiffel backend (maybe using the acyclic visitor)

Extra points to fix:
  • sedb — it lost some of its power in the latest releases (some break points disappeared)
  • Liberty core — will be removed; that code is dead.
  • some bugs in inline agents parsing (SmartEiffel segfault)
  • some bugs in boost mode (invalid C code)

The Liberty libraries (both native and wrappers), on the other hand, are here to stay. They deserve being enhanced.

Spread the news :-)

Sunday, December 26, 2010

Coroutines

The linked commit introduces coroutines in the Eiffel world.

The concept is implemented in the Liberty repository, but that should work in a pristine SmartEiffel too.

Enjoy!