An associative array or hash type
An Assoc_Type
object is like an array except that it is
indexed using strings and not integers. Unlike an Array_Type
object, the size of an associative array is not fixed, but grows as
objects are added to the array. Another difference is that ordinary
arrays represent ordered object; however, the ordering of the
elements of an Assoc_Type
object is unspecified.
An Assoc_Type
object whose elements are of some data-type
d
may be created using using
A = Assoc_Type[d];
For example,
A = Assoc_Type[Int_Type];
will create an associative array of integers. To create an
associative array capable of storing an arbitrary type, use the form
A = Assoc_Type[];
An optional parameter may be used to specify a default value for array elements. For example,
A = Assoc_Type[Int_Type, -1];
creates an integer-valued associative array with a default element
value of -1. Then A["foo"]
will return -1 if the key
"foo"
does not exist in the array. Default values are
available only if the type was specified when the associative array
was created.
The following functions may be used with associative arrays:
assoc_get_keys
assoc_get_values
assoc_key_exists
assoc_delete_key
The length
function may be used to obtain the number of
elements in the array.
The foreach
construct may be used with associative arrays via
one of the following forms:
foreach k,v (A) {...}
foreach k (A) using ("keys") { ... }
foreach v (A) using ("values") { ... }
foreach k,v (A) using ("keys", "values") { ... }
In all the above forms, the loop is over all elements of the array
such that v=A[k]
.
List_Type, List_Type<@@ref>Array_TypeArray_Type, Struct_Type
A type representing a C stdio object
An File_Type
is the interpreter's representation of a C
stdio FILE object and is usually created using the fopen
function, i.e.,
fp = fopen ("file.dat", "r");
Functions that utilize the File_Type
include:
fopen
fclose
fgets
fputs
ferror
feof
fflush
fprintf
fseek
ftell
fread
fwrite
fread_bytes
The foreach
construct may be used with File_Type
objects via one of the following forms:
foreach line (fp) {...}
foreach byte (A) using ("char") { ... } % read bytes
foreach line (A) using ("line") { ... } % read lines (default)
foreach line (A) using ("wsline") { ... } % whitespace stripped from lines
List_Type, List_Type<@@ref>Array_TypeArray_Type, Struct_Type
A list object
An object of type List_Type
represents a list, which is
defined as an ordered heterogeneous collection of objects.
A list may be created using, e.g.,
empty_list = {};
list_with_4_items = {[1:10], "three", 9, {1,2,3}};
Note that the last item of the list in the last example is also a
list. A List_Type object may be manipulated by the following
functions:
list_new
list_insert
list_append
list_delete
list_reverse
list_pop
A List_Type
object may be indexed using an array syntax with
the first item on the list given by an index of 0. The
length
function may be used to obtain the number of elements
in the list.
A copy of the list may be created using the @ operator, e.g.,
copy = @list
.
The foreach
statement may be used with a List_Type
object to loop over its elements:
foreach elem (list) {....}
<@@ref>Array_TypeArray_Type, Assoc_Type, Struct_Type
A string object
An object of type String_Type
represents a string of bytes or
characters, which in general have different semantics depending upon
the UTF-8 mode.
The string obeys byte-semantics when indexed as an
array. That is, S[0]
will return the first byte of the
string S
. For character semantics, the nth character in the
string may be obtained using substr
function.
The foreach
statement may be used with a String_Type
object S
to loop over its bytes:
foreach b (S) {....}
foreach b (S) using ("bytes") {....}
To loop over its characters, the following form may be used:
foreach c (S) using ("chars") {...}
When UTF-8 mode is not in effect, the byte and character forms will
produce the same sequence. Otherwise, the string will be decoded
to generate the (wide) character sequence. If the string contains
an invalid UTF-8 encoded character, successive bytes of the invalid
sequence will be returned as negative integers. For example,
"a\xAB\x{AB}"
specifies a string composed of the character
a
, a byte 0xAB
, and the character 0xAB
. In
this case,
foreach c ("a\xAB\x{AB}") {...}
will produce the integer-valued sequence 'a', -0xAB, 0xAB
.
<@@ref>Array_TypeArray_Type, _slang_utf8_ok
A structure datatype
A Struct_Type
object with fields f1
, f2
,...,
fN
may be created using
s = struct { f1, f2, ..., fN };
The fields may be accessed via the "dot" operator, e.g.,
s.f1 = 3;
if (s12.f1 == 4) s.f1++;
By default, all fields will be initialized to NULL
.
A structure may also be created using the dereference operator (@):
s = @Struct_Type ("f1", "f2", ..., "fN");
s = @Struct_Type ( ["f1", "f2", ..., "fN"] );
Functions for manipulating structure fields include:
_push_struct_field_values
get_struct_field
get_struct_field_names
set_struct_field
set_struct_fields
The foreach
loop may be used to loop over elements of a linked
list. Suppose that first structure in the list is called
root
, and that the child
field is used to form the
chain. Then one may walk the list using:
foreach s (root) using ("child")
{
% s will take on successive values in the list
.
.
}
The loop will terminate when the last elements child
field is
NULL. If no ``linking'' field is specified, the field name will
default to next
.
User-defined data types are similar to the Struct_Type
. A
type, e.g., Vector_Type
may be created using:
typedef struct { x, y, z } Vector_Type;
Objects of this type may be created via the @ operator, e.g.,
v = @Vector_Type;
It is recommended that this be used in a function for creating such
types, e.g.,
define vector (x, y, z)
{
variable v = @Vector_Type;
v.x = x;
v.y = y;
v.z = z;
return v;
}
The action of the binary and unary operators may be defined for such
types. Consider the "+" operator. First define a function for
adding two Vector_Type
objects:
static define vector_add (v1, v2)
{
return vector (v1.x+v2.x, v1.y+v2.y, v1.z, v2.z);
}
Then use
__add_binary ("+", Vector_Type, &vector_add, Vector_Type, Vector_Type);
to indicate that the function is to be called whenever the "+"
binary operation between two Vector_Type
objects takes place,
e.g.,
V1 = vector (1, 2, 3);
V2 = vector (8, 9, 1);
V3 = V1 + V2;
will assigned the vector (9, 11, 4) to V3
. Similarly, the
"*"
operator between scalars and vectors may be defined using:
static define vector_scalar_mul (v, a)
{
return vector (a*v.x, a*v.y, a*v.z);
}
static define scalar_vector_mul (a, v)
{
return vector_scalar_mul (v, a);
}
__add_binary ("*", Vector_Type, &scalar_vector_mul, Any_Type, Vector_Type);
__add_binary ("*", Vector_Type, &vector_scalar_mul, Vector_Type, Any_Type);
Related functions include:
__add_unary
__add_string
__add_destroy