This chapter describes features that were added to various 2.0
releases. For a much more complete and detailed list of changes, see
the changes.txt
file that is distributed with the library.
expression = condition ? val1 : val2
If condition is non-zero, then expression = val1,
otherwise expression = val2.
while (1)
{
loop (10)
{
break 2;
}
}
will cause both loops to be terminated.
"This is a \
multiline \
string"
`This is
another multiline
string that
does not require
a \ for continuation`
List_Type
objects may be indexed using an array of indices
instead of just a single scalar index.The following intrinsic function were added in version 2.2:
sumsq
Equivalent to sum(x*x)
.
expm1
More accurate version of exp(x)-1
for x
near 0.
log1p
More accurate version of log(1+x)
for x
near 0.
list_to_array
Creates an array from a list.
string_matches
A convenient alternative to the string_match
and
string_match_nth
functions.
_close
Close an integer descriptor.
_fileno
Returns the descriptor as an integer.
dup2_fd
Duplicates a file descriptor via the dup2
POSIX function.
getsid, killpg, getpriority, setpriority
These functions correspond to the corresponding POSIX functions.
ldexp, frexp
If x == a*2^b
, where 0.5<=a<1.0
then
(a,b)=frexp(x)
, and x=ldexp(a,b)
.
The following functions have been enhanced:
hypot
If given a single array argument X
, it returns the equivalent
of sqrt(sum(X*X)
.
polynom
The calling interface to this function was changed and support added for arrays.
The following modules were added to version 2.2:
zlib
A module that wraps the popular z compression library.
fork
A module that wraps the fork
, exec*
, and
waitpid
functions.
sysconf
A module that implements interfaces to the POSIX
sysconf
, pathconf
, and confstr
functions.
The following library files and functions were add to slsh:
process.sl
The code in this file utilizes the fork
module to implement
the new_process
function, which allows the caller to easily
create and communicate with subprocesses and pipelines.
||
and &&
have been added to the languange. The use of orelse
and
andelse
constructs are nolonger necessary nor encouraged.
s = struct {foo = 3, bar = "hello" };
a<b<c
are now interpretered as
(a<b)and(b<c)
.ifnot
keyword was added as an alternative to !if
. The
use of !if
has been deprecated.
loop (20)
{
if (this ())
break; % The then clause will NOT get executed
}
then do_that ();
Note: then
is now a reserved word.[a:b:#N]
, where the elements are uniformly
spaced and run from a to b, inclusive.&A[3]
, &s.foo
.
try { something (); }
catch AnyError: { do_this (); throw; }
The following intrinsic function were added in version 2.1:
wherenot(x)
Equivalent to where (not(x))
_$(str)
Evaluates strings with embedded "dollar" variables, e.g.,
_$("$TERM")
.
__push_list/__pop_list
Push list items onto the stack
prod(x)
Computes the product of an array a[0]*a[1]*...
minabs(x), maxabs(x)
Equivalent to min(abs(x))
and max(abs(x))
, resp.
getpgrp, setgid, getpgid
Get and set the process group ids (Unix).
setsid
Create a new session (Unix).
The following modules were added to version 2.1:
iconv
Performs character-set conversion using the iconv library.
onig
A regular expression module using oniguruma RE library.
The following library files and functions were add to slsh:
readascii
A flexible and power ascii (as opposed to binary) data file reader.
cmdopt
A set of functions that vastly simplify the parsing of command line options.
Also a history and completion mechanism was added to the S-Lang readline interface, and as a result, slsh now supports history and command/file completion.
Here is a brief list of some of the new features and improvements in S-Lang 2.0.
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.
file = "$HOME/src/slang-$VERSION/"$;
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);
(@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.
hypot
, atan2
, floor
, ceil
,
round
, isnan
, isinf
, and many more.
long long
integers.
X = 18446744073709551615ULL;
See the relevent chapters in in the manual for more information.
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.
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 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);
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:]];
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.
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 ();
}
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.
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.
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.
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.