1. Extending Euphoria with Fallbacks

Some time ago, I ran across the Lua language:

   http://www.tecgraf.puc-rio.br/lua/

There's a short paper at:

   http://www.tecgraf.puc-rio.br/lua/spe.html

One of the more interesting features is the handling of errors. It
uses
'fallbacks', which catch run-time abnormal conditions. The
programmer has
the option of catching illegal operations, and choosing what to do
about it.
Errors fall into classes, such as:

   "arith" - bad type, overflow
   "concat" - bad type
   "index" - out of range, bad type
   "range" - bad range, bad type
   "test" - bad type
   "assign" - bad type

I've embellished the list a bit, adding some classes that seem to
make sense
in Euphoria. For example, trying to add two sequences:

   ... "two" + "strings"

This is an error in Euphoria, because the sequences are of differing
lengths. If would trigger a fallback in the "arith" class, with
three
arguments:

  op = "add"
  arg1 = "this"
  arg2 = "that"

The neat thing about fallbacks is that they won't *break* any
existing code.
After all, they are only triggered when there's a runtime error. In
addition, the won't alter the runtime speed of Euphoria, if they are
never
used.

It's pretty obvious that you could try to use fallbacks to trigger a
shutdown routine, or possibly attempt to recover from errors. But
you can do
more than that: you can use them to extend the language.

As an example of what can be done with callbacks, I've put together
a few
examples (untested of course):

1. Convert strings to numbers, and numbers to strings automatically.

Example:

   integer i
   sequence s

   s = 123
   i = "456"

Code:

   function convert_to_string( object var, object expr )
      sequence result

      -- storing number in sequence?
      if sequence( var ) and atom( expr ) then
         -- convert to string
         return sprintf( "%g", val )

      -- storing sequence in number?
      elsif atom( val ) and sequence( var ) then
         -- attempt to convert to number
         result = value( var )
         if result[1] = GET_SUCCESS then
            return result[2]
         end if

      end if

      -- default
      return call_func( oldFallback, {var, val} )

   end function
   oldFallback = set_fallback("assign",
routine_id("convert_to_type"))

2. Allow the use of strings as indexes. This assumes that the first
element
in the sequence contains a list of all the keys, such as:

   cat = { {"name","color"}, "chester", "orange" }

Example:

   puts( 1, cat["name"] )

Code:

   function string_index(object s, object index)
     integer at
     if sequence( index ) then
        -- association list?
        if length( s ) = 2 then
           -- indexes stored at s[1],
           -- data in elements 2..end
           at = find( index, s[1] )
           if at then
              return at+1
           end if
        end if
     end if
     return call_func( oldFallback, {s, index} )
     end if
   end function
   oldFallback = setfallback("index", routine_id("string_index"))

3. Automatically clip ranges past end of strings to match size of
string:

Example:

   sequence s
   s = "123456789"
   ? s[1..20]

Code:

   function string_index(object s, object index )
      if is_string( s )
      and integer( iStart ) then
      end if
      return call_func( oldFallback1, {s, index} )
   end function
   oldFallback1 = set_fallback("index", routine_id("string_index"))

   function string_range(object s, object iStart, object iEnd)
      if is_string( s )
      and integer( iStart )
      and integer( iEnd ) then

        if iStart > length( s ) then
           iStart = length( s )
        end if

        if iEnd > length( iEnd ) then
           iEnd = length( iEnd )
        end if

        return s[iStart..iEnd]
      end if
      return call_func( oldFallback2, {s, iStart, iEnd} )
   end function
   oldFallback2 = set_fallback("range", routine_id("string_range"))

4. Make '=' behave like 'equal'. This requires two traps: one for
when '='
is passes sequences of different sizes, and one for when 'if' is
passed the
comparison of two equal sized strings.

Example:

   if "cat" = "dog" then ...

Code:


   function string_if(object op, object test)
     if equal( op, "if" )
     and sequence( test ) then
        -- sequence passed to 'if' statement
        return find( 0, arg )
     end if
     return call_func( ifFallback, {op, arg} )
   end function
   ifFallback = set_fallback("test", routine_id("string_if"))

   function string_eq( object op, object arg1, object arg2 )
     if equal( op, "=" ) then
        -- make it behave like 'equal'
        return equal( arg1, arg2 )
     end if
     return call_func( oldFallback, {op, arg1, arg2} )
   end function
   oldFallback = setfallback("arith", routine_id("string_eq"))

-- David Cuny

new topic     » topic index » view message » categorize

2. Re: Extending Euphoria with Fallbacks

On 26 Mar 2001, at 16:39, David Cuny wrote:


> 
> Some time ago, I ran across the Lua language:
> 
>    http://www.tecgraf.puc-rio.br/lua/
> 
> There's a short paper at:
> 
>    http://www.tecgraf.puc-rio.br/lua/spe.html
> 
> One of the more interesting features is the handling of errors. It
> uses
> 'fallbacks', which catch run-time abnormal conditions. The
> programmer has
> the option of catching illegal operations, and choosing what to do
> about it.

It also has:

dostring (string [, chunkname])
Executes a given string as a Lua chunk. If there is any error executing the
string,
then dostring returns nil. Otherwise, it returns the values returned by the
chunk,
or a non-nil value if the chunk returns no values. The optional parameter 
chunkname is the ``name of the chunk'', used in error messages and debug 
information. 


Kat

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu