Next Previous Contents

## 21. S-Lang 2 Interpreter NEWS

## 21.1 What's new for S-Lang 2

Here is a brief list of some of the new features and improvements in S-Lang 2.0.

- slsh, the generic S-Lang interpreter now supports and interactive command-line mode with readline support.
- Native support for Unicode via UTF-8 throughout the library.
- A `List_Type` object has been added to the language, e.g.,

  > `

  >          x = {1, 2.7, "foo", [1:10]};

  > `

  will create a (heterogeneous) list of 4 elements.
- A much improved exception handling model.
- Variable expansion within string literals:

  > `

  >         file = "$HOME/src/slang-$VERSION/"$;

  > `

- Operator overloading for user-defined types. For example it is possible to define a meaning to `X+Y` where `X` and `Y` are defined as

  > `

  >         typedef struct { x, y, z } Vector;
  >         define vector (x,y,z) { variable v = @Vector; v.x=x; v.y=y; v.z=z;}
  >         X = vector (1,2,3);
  >         Y = vector (4,5,6);

  > `

- Syntactic sugar for objected-oriented style method calls. S-Lang 1 code such as

  > `

  >          (@s.method)(s, args);

  > `

  may be written much more simply as

  > `

  >          s.method(args);

  > `

  This should make "object-oriented" code somewhat more readable. See also the next section if your code uses constructs such as

  > `

  >          @s.method(args);

  > `

  because it is not supported by S-Lang 2.
- More intrinsic functions including math functions such as `hypot`, `atan2`, `floor`, `ceil`, `round`, `isnan`, `isinf`, and many more.
- Support for `long long` integers.

  > `

  >         X = 18446744073709551615ULL;

  > `

- Large file support
- Performance improvements. The S-Lang 2 interpreter is about 20 percent faster for many operations than the previous version.
- Better debugging support including an interactive debugger. See the section on Using the sldb debugger for more information.

See the relevent chapters in in the manual for more information.

## 21.2 Upgrading to S-Lang 2

For the most part S-Lang 2 is backwards-compatible with S-Lang 1. However there are a few important differences that need to be understood before upgrading to version 2.

++ and -- operators in function calls

  Previously the `++` and {--} operators were permitted in a function argument list, e.g.,

  > `

  >         some_function (x++, x);

  > `

  Such uses are flagged as syntax errors and need to be changed to

  > `

  >         x++; some_function (x);

  > `

Array indexing of strings

  Array indexing of strings uses byte-semantics and not character-semantics. This distinction is important only if UTF-8 mode is in effect. If you use array indexing with functions that use character semantics, then your code may not work properly in UTF-8 mode. For example, one might have used

  > `

  >          i = is_substr (a, b);
  >          if (i) c = a[[0:i-2]];

  > `

  to extract that portion of `a` that preceeds the occurrence of `b` in `a`. This may nolonger work in UTF-8 mode where bytes and characters are not generally the same. The correct way to write the above is to use the `substr` function since it uses character semantics:

  > `

  >          i = is_substr (a, b);
  >          if (i) c = substr (a, 1, i-1);

  > `

Array indexing with negative integer ranges

  Previously the interpretation of a range array was context sensitive. In an indexing situation `[0:-1]` was used to index from the first through the last element of an array, but outside this context, `[0:-1]` was an empty array. For S-Lang 2, the meaning of such arrays is always the same regardless of the context. Since by itself `[0:-1]` represents an empty array, indexing with such an array will also produce an empty array. The behavior of scalar indices has not changed: `A[-1]` still refers to the last element of the array.

  Range arrays with an implied endpoint make sense only in indexing situations. Hence the value of the endpoint can be inferred from the context. Such arrays include `[*]`, `[:-1]`, etc.

  Code that use index-ranges with negative valued indices such as

  > `

  >            B = A[[0:-2]];    % Get all but the last element of A

  > `

  will have to be changed to use an array with an implied endpoint:

  > `

  >            B = A[[:-2]];     % Get all but the last element of A

  > `

  Similarly, code such as

  > `

  >            B = A[[-3:-1]];   % Get the last 3 elements of A

  > `

  must be changed to

  > `

  >            B = A[[-3:]];

  > `

Dereferencing function members of a structure

  Support for the non-parenthesized form of function member dereferencing has been dropped. Code such as

  > `

  >          @s.foo(args);

  > `

  will need to be changed to use the parenthesized form:

  > `

  >          (@s.foo)(args);

  > `

  The latter form will work in both S-Lang 1 and S-Lang 2.

  If your code passes the structure as the first argument of the method call, e.g.,

  > `

  >          (@s.foo)(s, moreargs);

  > `

  then it may be changed to

  > `

  >          s.foo (moreargs);

  > `

  However, this objected-oriented form of method calling is not supported by S-Lang 1.
ERROR_BLOCKS

  Exception handling via `ERROR_BLOCKS` is still supported but deprecated. If your code uses `ERROR_BLOCKS` it should be changed to use the new exception handling model. For example, code that looks like:

  > `

  >            ERROR_BLOCK { cleanup_after_error (); }
  >            do_something ();
  >               .
  >               .

  > `

  should be changed to:

  > `

  >            variable e;
  >            try (e)
  >              {
  >                 do_something ();
  >                   .
  >                   .
  >              }
  >            catch RunTimeError:
  >              {
  >                 cleanup_after_error ();
  >                 throw e.error, e.message;
  >              }

  > `

  Code that makes use of `EXECUTE_ERROR_BLOCK`

  > `

  >            ERROR_BLOCK { cleanup_after_error (); }
  >            do_something ();
  >               .
  >               .
  >            EXECUTE_ERROR_BLOCK;

  > `

  should be changed to make use of a `finally` clause:

  > `

  >            variable e;
  >            try (e)
  >              {
  >                 do_something ();
  >                   .
  >                   .
  >              }
  >            finally
  >              {
  >                 cleanup_after_error ();
  >              }

  > `

  It is not possible to emulate the complete semantics of the `_clear_error` function. However, those semantics are flawed and fixing the problems associated with the use of `_clear_error` was one of the primary reasons for the new exception handling model. The main problem with the `_clear_error` method is that it causes execution to resume at the byte-code following the code that triggered the error. As such, `_clear_error` defines no absolute resumption point. In contrast, the try-catch exception model has well-defined points of execution. With the above caveats, code such as

  > `

  >            ERROR_BLOCK { cleanup_after_error (); _clear_error ();}
  >            do_something ();
  >               .
  >               .

  > `

  should be changed to:

  > `

  >            variable e;
  >            try (e)
  >              {
  >                 do_something ();
  >                   .
  >                   .
  >              }
  >            catch RunTimeError:
  >              {
  >                 cleanup_after_error ();
  >              }

  > `

  And code using `_clear_error` in conjunction with `EXECUTE_ERROR_BLOCK`:

  > `

  >            ERROR_BLOCK { cleanup_after_error (); _clear_error ();}
  >            do_something ();
  >               .
  >               .
  >            EXECUTE_ERROR_BLOCK;

  > `

  should be changed to:

  > `

  >            variable e;
  >            try (e)
  >              {
  >                 do_something ();
  >                   .
  >                   .
  >              }
  >            catch RunTimeError:
  >              {
  >                 cleanup_after_error ();
  >              }
  >            finally:
  >              {
  >                 cleanup_after_error ();
  >              }

  > `

fread

  When reading `Char_Type` and `UChar_Type` objects the S-Lang 1 version of `fread` returned a binary string (`BString_Type` if the number of characters read was greater than one, or a `U/Char_Type` if the number read was one. In other words, the resulting type depended upon how many bytes were read with no way to predict the resulting type in advance. In contrast, when reading, e.g, `Int_Type` objects, `fread` returned an `Int_Type` when it read one integer, or an array of `Int_Type` if more than one was read. For S-Lang 2, the behavior of `fread` with respect to `UChar_Type` and `Char_Type` types was changed to have the same semantics as the other data types.

  The upshot is that code that used

  > `

  >             nread = fread (&str, Char_Type, num_wanted, fp)

  > `

  will no longer result in `str` being a `BString_Type` if `nread > 1`. Instead, `str` will now become a `Char_Type[nread]` object. In order to read a specified number of bytes from a file in the form of a string, use the `fread_bytes` function:

  > `

  >            #if (_slang_version >= 20000)
  >            nread = fread_bytes (&str, num_wanted, fp);
  >            #else
  >            nread = fread (&str, Char_Type, num_wanted, fp)
  >            #endif

  > `

  The above will work with both versions of the interpreter.
strtrans

  The `strtrans` function has been changed to support Unicode. One ramification of this is that when mapping from one range of characters to another, the length of the ranges must now be equal.

str_delete_chars

  This function was changed to support unicode character classes. Code such as

  > `

  >          y = str_delete_chars (x, "\\a");

  > `

  is now implies the deletion of all alphabetic characters from `x`. Previously it meant to delete the backslashes and `a`s from from `x`. Use

  > `

  >          y = str_delete_chars (x, "\\\\a");

  > `

  to achieve the latter.
substr, is_substr, strsub

  These functions use character-semantics and not byte-semantics. The distinction is important in UTF-8 mode. If you use array indexing in conjunction with these functions, then read on.

Next Previous Contents