Next Previous Contents

4. Data Types and Literal Constants

The current implementation of the S-Lang language permits up to 256 distinct data types, including predefined data types such as integer and floating point, as well as specialized applications specific data types. It is also possible to create new data types in the language using the typedef mechanism.

Literal constants are objects such as the integer 3 or the string "hello". The actual data type given to a literal constant depends upon the syntax of the constant. The following sections describe the syntax of literals of specific data types.

4.1 Predefined Data Types

The current version of S-Lang defines integer, floating point, complex, and string types. It also defines special purpose data types such as Null_Type, DataType_Type, and Ref_Type. These types are discussed below.

Integers

The basic S-Lang language supports integers only as signed values. Unsigned and long integers are not part of the basic language, though it is possible for applications to define them. On most 32 bit systems, there is no difference between an integer and a long integer; however, they may differ on 16 and 64 bit systems. Generally speaking, on a 16 bit system, integers are 16 bit quantities with a range of -32767 to 32767. On a 32 bit system, integers range from -2147483648 to 2147483647.

An integer literal can be specified in one of several ways:

Any integer may be preceded by a minus sign to indicate that it is a negative integer.

Floating Point Numbers

Double precision floating point literals must contain either a decimal point or an exponent (or both). Here are examples of specifying the same floating point number:

         12.    12.0    12e0   1.2e1   120e-1   .12e2   0.12e2
Note that 12 is not a floating point number since it contains neither a decimal point nor an exponent. In fact, 12 is an integer.

One may append the f character to the end of the number to indicate that the number is a single precision literal. This suffix will be ignored unless the application provides a single precision floating point type. The current implementation only provides support for double precision floating point numbers.

Complex Numbers

The language implements complex numbers as a pair of double precision floating point numbers. The first number in the pair forms the real part, while the second number forms the imaginary part. That is, a complex number may be regarded as the sum of a real number and an imaginary number.

Strictly speaking, the current implementation of the S-Lang does not support generic complex literals. However, it does support imaginary literals and a more generic complex number with a non-zero real part may be constructed from the imaginary literal via addition of a real number.

An imaginary literal is specified in the same way as a floating point literal except that i or j is appended. For example,

         12i    12.0i   12e0j
all represent the same imaginary number. Actually, 12i is really an imaginary integer except that S-Lang automatically promotes it to a double precision imaginary number.

A more generic complex number may be constructed from an imaginary literal via addition, e.g.,

        3.0 + 4.0i
produces a complex number whose real part is 3.0 and whose imaginary part is 4.0.

The intrinsic functions Real and Imag may be used to retrieve the real and imaginary parts of a complex number, respectively.

Strings

A string literal must be enclosed in double quotes as in:

      "This is a string".
Although there is no imposed limit on the length of a string, string literals must be less than 256 characters in length. It is possible to go beyond this limit by string concatenation, e.g.,
     "This is the first part of a long string"
       + "and this is the second half"
Any character except a newline (ASCII 10) or the null character (ASCII 0) may appear explicitly in a string literal. However, these characters may be used implicitely using the mechanism described below.

The backslash character is a special character and is used to include other special characters (such as a newline character) in the string. The special characters recognized are:

       \"    --  double quote
       \'    --  single quote
       \\    --  backslash
       \a    --  bell character (ASCII 7)
       \t    --  tab character (ASCII 9)
       \n    --  newline character (ASCII 10)
       \e    --  escape character (ASCII 27)
       \xhhh --  character expressed in HEXIDECIMAL notation
       \ooo  --  character expressed in OCTAL notation
       \dnnn --  character expressed in DECIMAL
For example, to include the double quote character as part of the string, it must be preceded by a backslash character, e.g.,
       "This is a \"quote\""
Similary, the next illustrates how a newline character may be included:
       "This is the first line\nand this is the second"

Null_Type

Objects of type Null_Type can have only one value: NULL. About the only thing that you can do with this data type is to assign it to variables and test for equality with other objects. Nevertheless, Null_Type is an important and extremely useful data type. Its main use stems from the fact that since it can be compared for equality with any other data type, it is ideal to represent the value of an object which does not yet have a value, or has an illegal value.

As a trivial example of its use, consider

      define add_numbers (a, b)
      {
         if (a == NULL) a = 0;
         if (b == NULL) b = 0;
         return a + b;
      }
      variable c = add_numbers (1, 2);
      variable d = add_numbers (1, NULL);
      variable e = add_numbers (1,);
      variable f = add_numbers (,);
It should be clear that after these statements have been executed, c will have a value of 3. It should also be clear that d will have a value of 1 because NULL has been passed as the second parameter. One feature of the language is that if a parameter has been omitted from a function call, the variable associated with that parameter will be set to NULL. Hence, e and f will be set to 1 and 0, respectively.

The Null_Type data type also plays an important role in the context of structures.

Ref_Type

Objects of Ref_Type are created using the unary reference operator &. Such objects may be dereferenced using the dereference operator @. For example,

      variable sin_ref = &sin;
      variable y = @sin_ref (1.0);
creates a reference to the sin function and assigns it to sin_ref. The second statement uses the dereference operator to call the function that sin_ref references.

The Ref_Type is useful for passing functions as arguments to other functions, or for returning information from a function via its parameter list. The dereference operator is also used to create an instance of a structure. For these reasons, further discussion of this important type can be found in section ??? and section ???.

Array_Type and Struct_Type

Variables of type Array_Type and Struct_Type are known as container objects. They are much more complicated than the simple data types discussed so far and each obeys a special syntax. For these reasons they are discussed in a separate chapters. See ???.

DataType_Type Type

S-Lang defines a type called DataType_Type. Objects of this type have values that are type names. For example, an integer is an object of type Integer_Type. The literals of DataType_Type include:

     Integer_Type         (integers)
     Double_Type          (double precision reals)
     Complex_Type         (complex numbers)
     String_Type          (strings)
     Struct_Type          (structures)
     Ref_Type             (references)
     Null_Type            (NULL)
     Array_Type           (arrays)
     DataType_Type        (data types)
as well as the names of any other types that an application defines.

The built-in function typeof returns returns the data type of its argument, i.e., a DataType_Type. For instance typeof(7) returns Integer_Type and typeof(Integer_Type) returns DataType_Type. One can use this function as in the following example:

      if (Integer_Type == typeof (x)) message ("x is an integer");
The literals of DataType_Type have other uses as well. One of the most common uses of these literals is to create arrays, e.g.,
        x = Complex_Type [100];
creates an array of 100 complex numbers and assigns it to x.

4.2 Typecasting: Converting from one Type to Another

Occasionally, it is necessary to convert from one data type to another. For example, if you need to print an object as a string, it may be necessary to convert it to a String_Type. The typecast function may be used to perform such conversions. For example, consider

      variable x = 10, y;
      y = typecast (x, Double_Type);
After execution of these statements, x will have the integer value 10 and y will have the double precision floating point value 10.0. If the object to be converted is an array, the typecast function will act upon all elements of the array. For example,
      variable x = [1:10];       % Array of integers
      variable y = typecast (x, Double_Type);
will create an array of 10 double precision values and assign it to y. One should also realize that it is not always possible to perform a typecast. For example, any attempt to convert an Integer_Type to a Null_Type will result in a run-time error.

Often the interpreter will perform implicit type conversions as necessary to complete calculations. For example, when multiplying an Integer_Type with a Double_Type, it will convert the Integer_Type to a Double_Type for the purpose of the calculation. Thus, the example involving the conversion of an array of integers to an array of doubles could have been performed by multiplication by 1.0, i.e.,

      variable x = [1:10];       % Array of integers
      variable y = 1.0 * x;

The string intrinsic function is similar to the typecast function except that it converts an object to a string representation. It is important to understand that a typecast from some type to String_Type is not the same as converting an object to its string operation. That is, typecast(x,String_Type) is not equivalent to string(x). The reason for this is that when given an array, the typecast function acts on each element of the array to produce another array, whereas the string function produces a a string.

The string function is useful for printing the value of an object. This use is illustrated in the following simple example:

      define print_object (x)
      {
         message (string (x));
      }
Here, the message function has been used because it writes a string to the display. If the string function was not used and the message function was passed an integer, a type-mismatch error would have resulted.


Next Previous Contents