Sophie

Sophie

distrib > Mandriva > 8.1 > i586 > by-pkgid > 700475c8ae73fb4d57b6df4485c29e1c > files > 186

slang-doc-1.4.4-2mdk.i586.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
 <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9">
 <TITLE> A Guide to the S-Lang Language: Operators</TITLE>
 <LINK HREF="slang-8.html" REL=next>
 <LINK HREF="slang-6.html" REL=previous>
 <LINK HREF="slang.html#toc7" REL=contents>
</HEAD>
<BODY>
<A HREF="slang-8.html">Next</A>
<A HREF="slang-6.html">Previous</A>
<A HREF="slang.html#toc7">Contents</A>
<HR>
<H2><A NAME="s7">7. Operators</A></H2>

<P> 
<P><B>S-Lang</B> supports a variety of operators that are grouped into three
classes: assignment operators, binary operators, and unary operators.
<P>An assignment operator is used to assign a value to a variable.
They will be discussed more fully in the context of the assignment
statement in section ???.
<P>An unary operator acts only upon a single quantity while a binary
operation is an operation between two quantities.  The boolean
operator <CODE>not</CODE> is an example of an unary operator.  Examples of
binary operators include the usual arithmetic operators
<CODE>+</CODE>, <CODE>-</CODE>, <CODE>*</CODE>, and <CODE>/</CODE>.  The operator given by
<CODE>-</CODE> can be either an unary operator (negation) or a binary operator
(subtraction); the actual operation is determined from the context
in which it is used.
<P>Binary operators are used in algebraic forms, e.g., <CODE>a + b</CODE>.
Unary operators fall in one of two classes: postfix-unary or
prefix-unary.  For example, in the expression <CODE>-x</CODE>, the minus
sign is a prefix-unary operator.
<P>Not all data types have binary or unary operations defined.  For
example, while <CODE>String_Type</CODE> objects support the <CODE>+</CODE>
operator, they do not admit the <CODE>*</CODE> operator.
<P>
<H2><A NAME="ss7.1">7.1 Unary Operators</A>
</H2>

<P>
<P>The <B>unary</B> operators operate only upon a single operand.  They
include: <CODE>not</CODE>, <CODE>~</CODE>, <CODE>-</CODE>, <CODE>@</CODE>, <CODE>&amp;</CODE>, as well as the
increment and decrement operators <CODE>++</CODE> and <CODE>--</CODE>,
respectively.
<P>The boolean operator <CODE>not</CODE> acts only upon integers and produces
<CODE>0</CODE> if its operand is non-zero, otherwise it produces <CODE>1</CODE>.
<P>The bit-level not operator <CODE>~</CODE> performs a similar function,
except that it operates on the individual bits of its integer
operand.
<P>The arithmetic negation operator <CODE>-</CODE> is the most well-known
unary operator.  It simply reverses the sign of its operand.
<P>The reference (<CODE>&amp;</CODE>) and dereference (<CODE>@</CODE>) operators will be
discussed in greater detail in section ???.  Similarly, the
increment (<CODE>++</CODE>) and decrement (<CODE>--</CODE>) operators will be
discussed in the context of the assignment operator.
<P>
<H2><A NAME="ss7.2">7.2 Binary Operators</A>
</H2>

<P> 
<P>The binary operators may be grouped according to several classes:
arithmetic operators, relational operators, boolean operators, and
bitwise operators.
<P>All binary and unary operators may be overloaded.  For example, the
arithmetic plus operator has been overloaded by the
<CODE>String_Type</CODE> data type to permit concatenation between strings.
<P>
<H3>Arithmetic Operators</H3>

<P> 
<P>The arithmetic operators include <CODE>+</CODE>, <CODE>-</CODE>, <CODE>*</CODE>, <CODE>/</CODE>,
which perform addition, subtraction, multiplication, and division,
respectively.  In addition to these, <B>S-Lang</B> supports the <CODE>mod</CODE>
operator as well as the power operator <CODE>^</CODE>.
<P>The data type of the result produced by the use of one of these
operators depends upon the data types of the binary participants.
If they are both integers, the result will be an integer.  However,
if the operands are not of the same type, they will be converted to
a common type before the operation is performed.  For example, if
one is a floating point value and the other is an integer, the
integer will be converted to a float. In general, the promotion
from one type to another is such that no information is lost, if
possible.  As an example, consider the expression <CODE>8/5</CODE> which
indicates division of the integer <CODE>8</CODE> by the integer <CODE>5</CODE>.
The result will be the integer <CODE>1</CODE> and <EM>not</EM> the floating
point value <CODE>1.6</CODE>.  However, <CODE>8/5.0</CODE> will produce
<CODE>1.6</CODE> because <CODE>5.0</CODE> is a floating point number.
<P>
<P>
<H3>Relational Operators</H3>

<P> 
<P>The relational operators are <CODE>&gt;</CODE>, <CODE>&gt;=</CODE>, <CODE>&lt;</CODE>, <CODE>&lt;=</CODE>,
<CODE>==</CODE>, and <CODE>!=</CODE>.  These perform the comparisons greater
than, greater than or equal, less than, less than or equal, equal,
and not equal, respectively.  The result of one of these
comparisons is the integer <CODE>1</CODE> if the comparison is true, or
<CODE>0</CODE> if the comparison is false.  For example, <CODE>6 &gt;= 5</CODE>
returns <CODE>1</CODE>, but <CODE>6 == 5</CODE> produces
<CODE>0</CODE>.
<P>
<P>
<H3>Boolean Operators</H3>

<P> 
There are only two boolean binary operators: <CODE>or</CODE> and
<CODE>and</CODE>.  These operators are defined only for integers and
produce an integer result.  The <CODE>or</CODE> operator returns <CODE>1</CODE>
if either of its operands are non-zero, otherwise it produces
<CODE>0</CODE>.  The <CODE>and</CODE> operator produces <CODE>1</CODE> if and only if
both its operands are non-zero, otherwise it produces <CODE>0</CODE>.
<P>Neither of these operators perform the so-called boolean
short-circuit evaluation.  For example, consider the expression:
<BLOCKQUOTE><CODE>
<PRE>
      (x != 0) and (1/x &gt; 10)
</PRE>
</CODE></BLOCKQUOTE>

Here, if <CODE>x</CODE> were to have a value of zero, a division by zero error
would occur because even though <CODE>x!=0</CODE> evaluates to zero, the
<CODE>and</CODE> operator is not short-circuited and the <CODE>1/x</CODE> expression
would still be evaluated.  Although these operators are not
short-circuited, <B>S-Lang</B> does have another mechanism of performing
short-circuit boolean evaluation via the <CODE>orelse</CODE> and
<CODE>andelse</CODE> expressions.  See below for information about these
constructs.
<P>
<P>
<H3>Bitwise Operators</H3>

<P> 
<P>The bitwise binary operators are defined only with integer operands
and are used for bit-level operations.  Operators that fall in this
class include <CODE>&amp;</CODE>, <CODE>|</CODE>, <CODE>shl</CODE>, <CODE>shr</CODE>, and
<CODE>xor</CODE>.  The <CODE>&amp;</CODE> operator performs a boolean AND operation
between the corresponding bits of the operands.  Similarly, the
<CODE>|</CODE> operator performs the boolean OR operation on the bits.
The bit-shifting operators <CODE>shl</CODE> and <CODE>shr</CODE> shift the bits
of the first operand by the number given by the second operand to
the left or right, respectively.  Finally, the <CODE>xor</CODE> performs
an EXCLUSIVE-OR operation.
<P>These operators are commonly used to manipulate variables whose
individual bits have distinct meanings.  In particular, <CODE>&amp;</CODE> is
usually used to test bits, <CODE>|</CODE> can be used to set bits, and
<CODE>xor</CODE> may be used to flip a bit.
<P>As an example of using <CODE>&amp;</CODE> to perform tests on bits, consider
the following: The <B>jed</B> text editor stores some of the information
about a buffer in a bitmapped integer variable.  The value of this
variable may be retrieved using the <B>jed</B> intrinsic function
<CODE>getbuf_info</CODE>, which actually returns four quantities: the
buffer flags, the name of the buffer, directory name, and file
name.  For the purposes of this section, only the buffer flags are
of interest and can be retrieved via a function such as
<BLOCKQUOTE><CODE>
<PRE>
      define get_buffer_flags ()
      {
         variable flags;
         (,,,flags) = getbuf_info ();
         return flags;
      }
</PRE>
</CODE></BLOCKQUOTE>

The buffer flags is a bitmapped quantity where the 0th bit
indicates whether or not the buffer has been modified, the first
bit indicates whether or not autosave has been enabled for the
buffer, and so on.  Consider for the moment the task of determining
if the buffer has been modified.  This can be
determined by looking at the zeroth bit, if it is <CODE>0</CODE> the
buffer has not been modified, otherwise it has.  Thus we can create
the function,
<BLOCKQUOTE><CODE>
<PRE>
     define is_buffer_modified ()
     {
        variable flags = get_buffer_flags ();
        return (flags &amp; 1);
     }
</PRE>
</CODE></BLOCKQUOTE>

where the integer <CODE>1</CODE> has been used since it has all of its
bits set to <CODE>0</CODE>, except for the zeroth one, which is set to
<CODE>1</CODE>.  (At this point, it should also be apparent that bits are
numbered from zero, thus an <CODE>8</CODE> bit integer consists of bits
<CODE>0</CODE> to <CODE>7</CODE>, where <CODE>0</CODE> is the least significant bit and
<CODE>7</CODE> is the most significant one.)  Similarly, we can create another
function
<BLOCKQUOTE><CODE>
<PRE>
     define is_autosave_on ()
     {
        variable flags = get_buffer_flags ();
        return (flags &amp; 2);
     }
</PRE>
</CODE></BLOCKQUOTE>

to determine whether or not autosave has been turned on for the
buffer.
<P>The <CODE>shl</CODE> operator may be used to form the integer with only
the <EM>nth</EM> bit set.  For example, <CODE>1 shl 6</CODE> produces an
integer with all bits set to zero except the sixth bit, which is
set to one.  The following example exploits this fact:
<BLOCKQUOTE><CODE>
<PRE>
     define test_nth_bit (flags, nth)
     {
        return flags &amp; (1 shl nth);
     }
</PRE>
</CODE></BLOCKQUOTE>
<P>
<P>
<H3>Namespace operator</H3>

<P>The operator <CODE>-&gt;</CODE> is used to in conjunction with the name of a
namespace to access an object within the namespace.  For example,
if <CODE>A</CODE> is the name of a namespace containing the variable
<CODE>v</CODE>, then <CODE>A-&gt;v</CODE> refers to that variable.
<P>
<H3>Operator Precedence</H3>

<P>
<P>
<H3>Binary Operators and Functions Returning Multiple Values</H3>

<P> 
Care must be exercised when using binary operators with an operand
the returns multiple values.  In fact, the current implementation
of the <B>S-Lang</B> language will produce incorrect results if both
operands of a binary expression return multiple values.  <EM>At
most, only one of operands of a binary expression can return
multiple values, and that operand must be the first one, not the
second.</EM>  For example,
<BLOCKQUOTE><CODE>
<PRE>
    define read_line (fp)
    {
       variable line, status;
       
       status = fgets (&amp;line, fp);
       if (status == -1)
         return -1;
       return (line, status);
    }
</PRE>
</CODE></BLOCKQUOTE>

defines a function, <CODE>read_line</CODE> that takes a single argument, a
handle to an open file, and returns one or two values, depending
upon the return value of <CODE>fgets</CODE>.  Now consider
<BLOCKQUOTE><CODE>
<PRE>
        while (read_line (fp) &gt; 0)
          {
             text = ();
             % Do something with text
             .
             .
          }
</PRE>
</CODE></BLOCKQUOTE>

Here the relational binary operator <CODE>&gt;</CODE> forms a comparison
between one of the return values (the one at the top of the stack)
and <CODE>0</CODE>.  In accordance with the above rule, since <CODE>read_line</CODE>
returns multiple values, it occurs as the left binary operand.
Putting it on the right as in
<BLOCKQUOTE><CODE>
<PRE>
        while (0 &lt; read_line (fp))    % Incorrect
          {
             text = ();
             % Do something with text
             .
             .
          }
</PRE>
</CODE></BLOCKQUOTE>

violates the rule and will result in the wrong answer.
<P>
<P>
<P>
<H2><A NAME="ss7.3">7.3 Mixing Integer and Floating Point Arithmetic</A>
</H2>

<P>
<P>If a binary operation (<CODE>+</CODE>, <CODE>-</CODE>, <CODE>*</CODE> , <CODE>/</CODE>) is
performed on two integers, the result is an integer.  If at least
one of the operands is a float, the other is converted to float and
the result is float.  For example:
<BLOCKQUOTE><CODE>
<PRE>
      11 / 2           --&gt; 5   (integer)
      11 / 2.0         --&gt; 5.5 (float)
      11.0 / 2         --&gt; 5.5 (float)
      11.0 / 2.0       --&gt; 5.5 (float)
</PRE>
</CODE></BLOCKQUOTE>

Finally note that only integers may be used as array indices, 
loop control variables, and bit operations.  The conversion
functions, <CODE>int</CODE> and <CODE>float</CODE>, may be used convert between
floats and ints where appropriate, e.g.,
<BLOCKQUOTE><CODE>
<PRE>
      int (1.5)         --&gt; 1 (integer)
      float(1.5)        --&gt; 1.5 (float)
      float (1)         --&gt; 1.0 (float)
</PRE>
</CODE></BLOCKQUOTE>
<P>
<H2><A NAME="ss7.4">7.4 Short Circuit Boolean Evaluation</A>
</H2>

<P>
<P>The boolean operators <CODE>or</CODE> and <CODE>and</CODE> <EM>are not short
circuited</EM> as they are in some languages.  <B>S-Lang</B> uses 
<CODE>orelse</CODE> and <CODE>andelse</CODE> expressions for short circuit boolean
evaluation.  However, these are not binary operators. Expressions
of the form:
<BLOCKQUOTE><CODE>
<EM>expr-1</EM> and <EM>expr-2</EM> and ... <EM>expr-n</EM>
</CODE></BLOCKQUOTE>

can be replaced by the short circuited version using <CODE>andelse</CODE>:
<BLOCKQUOTE><CODE>
andelse {<EM>expr-1</EM>} {<EM>expr-2</EM>} ... {<EM>expr-n</EM>}
</CODE></BLOCKQUOTE>

A similar syntax holds for the <CODE>orelse</CODE> operator.  For example, consider
the statement:
<BLOCKQUOTE><CODE>
<PRE>
      if ((x != 0) and (1/x &gt; 10)) do_something ();
</PRE>
</CODE></BLOCKQUOTE>

Here, if <CODE>x</CODE> were to have a value of zero, a division by zero error
would occur because even though <CODE>x!=0</CODE> evaluates to zero, the
<CODE>and</CODE> operator is not short circuited and the <CODE>1/x</CODE> expression
would be evaluated causing division by zero. For this case, the
<CODE>andelse</CODE> expression could be used to avoid the problem:
<BLOCKQUOTE><CODE>
<PRE>
      if (andelse
          {x != 0}
          {1 / x &gt; 10})  do_something ();
</PRE>
</CODE></BLOCKQUOTE>
<P>
<P>
<HR>
<A HREF="slang-8.html">Next</A>
<A HREF="slang-6.html">Previous</A>
<A HREF="slang.html#toc7">Contents</A>
</BODY>
</HTML>