Types in "steve"

The int type

An int is a whole number, identical to the int type in C.

int operators

ints can be operated on using the following mathematical operators, which operate just like their C counterparts: +, -, *, /, % and ^ (power). Divisions or mods by zero are treated as errors and will stop the execution of the simulation. The absolute value of an integer is given by | integer expression |.

Conversions to Other Types

ints can be converted to floats automatically in expressions or during assignments, but cannot be converted to any other type.

The float type

A real number, also known as "double", identical to the double type in C. Internally, floats are represented by 8-byte doubles.

float Operators

All of the operators used for ints—including %—can also be applied to floats.

Conversions to Other Types

floats can be converted to (and from) ints automatically in expressions or assignments. floats cannot be converted to any other type.

The object Type

An object is an instance of a steve class.

object Operators

objects cannot used in mathematical expressions as some of the other types can. Instead, objects are mainly used for one type of expression: method calling. Method calling is outlined in the section Method Calls (the section called “Method Calls”).

Conversion to Other Types

Objects cannot be explicitly converted to other types. They do, however, have meaning as "boolean" (true or false) expressions in control structures (the section called “Program Control Structures”). If used in the context of a boolean expression (like an if statement, the section called “The if Statement”), the expression is true only if the variable refers to an active object. This means that an object variable which has not yet been associated with an instance in the simulation is false.

The vector Type

A vector is used to represent a point or vector in 3D space. A vector is expressed as three floating point numbers, such as (1.0, 2.0, 5.0).

vector Operators

Vectors may be added (+) to and subtracted (-) from other vectors, which yields another vector. Vectors may be multiplied (*) or divided (/) by ints or floats, which also results in other vectors. The length of the vector is given using the following construct: | vector expression |.

Some examples of using vectors follow:

v = (1, 2, 3).  # sets the vector to a constant vector.

v = v * 4.      # multiplies the vector by 4

v = v / |v|.    # normalizes the vector by dividing it by it's own 
                                # length such that the new length is 1.

Individual vector components can be extracted or set using the "::" notation:

xValue = myVector::x.

myVector::y = 100.

Starting in breve 2.5, the standard list index syntax may also be used with indices 0, 1, and 2:

xValue = myVector{ 0 }.

myVector{ 1 } = 100.

Conversions to Other Types

Vectors cannot be converted to any other types. They do, however, have meaning as "boolean" (true or false) expressions in control structures (the section called “Program Control Structures”). If used in the context of a boolean expression (like an if statement, the section called “The if Statement”), the vector will be true if it's length is greater than 0, and false if its length is equal to 0. This is to say that only the vector (0, 0, 0) is false in a boolean context.

The matrix type

A matrix in steve refers to a 3x3 matrix which describes a transformation in 3D space. Using transformation matrices is somewhat advanced and they are not generally used in most simulations. Still, they may be useful when dealing with physical simulation.

Matrices may be written in steve as three comma-separated vectors, enclosed in braces ('[' and ']'), as in this example:

# the matrix m will be initialized to:
#
# [ 1 2 3 ]
# [ 4 5 6 ]
# [ 7 8 9 ]

m = [ (1, 2, 3), (4, 5, 6), (7, 8, 9) ].

Matrix component can be extracted using the list index syntax. Each row of the matrix is a vector:

myVector = myMatrix{ 0 }.

myMatrix{ 1 } = ( 1, 2, 3 ).

Individual numbers can be extracted by the matrix as a two-dimensional list:

myNumber = myMatrix{ 0 }{ 0 }.

myMatrix{ 1 }{ 1 } = 100.

matrix Operators

Matrices may be multiplied (*), divided (/), added (+) to and subtracted (-) from other matrices. The results of these operations are other matrices.

Matrices may be multiplied (*) or divided (/) by scalars (ints and doubles). The result of these operations are other matrices.

Matrices may be used to transform vectors by multiplying the matrix times the vector (*). The result of this operation is a vector.

Conversions to Other Types

Matrices cannot be converted to any other types. They do, however, have meaning as "boolean" (true or false) expressions in control structures (the section called “Program Control Structures”). If used in the context of a boolean expression (like an if statement, the section called “The if Statement”), the expression will be true if there are any non-zero values in the matrix. This means that a matrix of all zeros will be false, while all other matrices are true.

The list Type

The list datatype allows you to keep a list of other variables. lists can contain any datatype, including other lists. lists can even contain multiple datatypes simultaneously.

lists are formed using the syntax { item1, , item2, , ... }.

Some simple examples of constructing lists are shown below:

myList = { 1, 2, 3.0 }.                 # a list of numbers (both int and float)
myList = { "a", "b", "c" }.             # a list of strings
myList = { "a", 30, new Mobile }.       # a list of mixed types
myList = { 1, "a", { "dog", "cow" } }.  # a list with a nested list

An important feature of lists in steve is that they are always passed by reference and are not copied. This means that if you pass a list to a function, then any modifications done to the list inside the function will modify the original list.

list Operators

The following operations can be used with list expressions:

  • insert expression, at list, { index }: inserts expression at the specified index in the list, shifting up other list elements with higher indices

  • remove list, { index }: removes the element of list at the specified index and returns it, shifting down other list elements with higher indices

  • push expression, onto list: appends expression onto the end of list

  • pop list: removes the last element of list and returns it

  • prepend expression, onto list: prepends expression onto the start of list

  • unprepend list: removes the first element of list and returns it

  • list, { expression }: returns the element of the list at offset expression. The expression index is zero based, as in C, such that 0 refers to the first element, 1 to the second, and so forth. If the offset expression is less than zero, or greater than the length of the list minus one (because the access is zero based), an error is triggered and the simulation is stopped.

  • list, { expression, } = value: sets an element of the list at offset expression to value. The offset index is again zero based. If the offset expression is less than zero or greater than the size of the list an error is triggered and the simulation is stopped. If the offset expression is equal to the size of the list, the list is extended by one element; the operation has the same effect as pushing a value on to the end.

  • sort list, with method-name: sorts list using the method specified with method-name. method-name must be a method which takes two list elements (the keywords are unimportant) and compares them, returning a negative number if the first list element belongs before the second in the sorted list, a positive number if the second belongs before the first, and 0 if the two entries are equal. In most cases, this confusing sounding method returns a certain value associated with one argument minus the same value in the other.

    Unlike the perl sort operator, sort operates on the list it is given and does not return a copy of it. This means that the original list is modified during the sort operation.

  • copylist list: copies the entire list. Normally, assigning a list to a variable will not copy the list but instead will yield two variables pointing to the same list.

  • | list |: gives the length of a list. Lists are automatically converted to integers when use in mathematical expressions, but this construct can be used too force the conversion.

Conversions to Other Types

lists can be converted to ints simply by using them in the context of integers. They can thus also be used as floats. In the event that the context of the expression does not force the list to become an integer, you can force it yourself by using it in a mathematical context:

myInt = (myList + 0).

The string Type

The string type holds a character string. A string is written in code (as in C) as a quoted string. For example, the built-in print operator is capable of printing strings:

print "this is a string".

string Operators

The following operations can be done one strings:

  • string { index }: returns, as a string, the letter at the specified index.

  • string { index } = otherString: replaces the letter at the specified location with the string otherString.

  • | string |: returns the length of the string.

In addition to the operators listed above, strings can be formatted using embedded variables. Variables can be embedded in strings so that the strings are interpreted dynamically, as in Perl. To indicate a variable embedded in a string, use the "$" character. The following, for example, will use the variable "self" in order to build a string to be printed:

print "my value is $self.".

This technique can be used to performing string concatenations as well:

$longstring = "$string1$string2".

Conversions to Other Types

strings can be converted to ints and floats, but not to any other types. types.

In the context of an int or a float, the string becomes the appropriate type by taking the numerical component of the string. For more information on this conversion, consult the man pages for the ANSI C atoi() (for ints) or atof() (for doubles) functions.

The hash Type

A hash is a type which works like a dictionary: it allows expressions ("values") to be stored and looked-up using other expressions as the "keys". The following example shows a steve hash being used like a dictionary:

dictionary (hash).

dictionary{ "dog" } = "a four-legged pet".
dictionary{ "fish" } = "a zero-legged pet".

# this will print the definition we stored above.

print "the definition of dog is: ", dictionary{ "dog" }.

As shown in this example, we're able to store data using strings as the keys. When data is later retrieved from the hash table using the same key, the value stored previously is returned.

hashes are not limited to using strings as keys. They can use any valid type. The most useful application is a hash table which uses objects as keys. In this way, relationships between objects can be stored in a hash. Consider an object which wants to keep track of neighbors it has encountered previously:

# let's say that this method gets called when a neighbor is seen...
# if the neighbor has already been seen, print a message — otherwise,
# just add it to the hash for next time!

+ to meet with neighbor (object):
        if seenHash{ neighbor }: print "i've seen this neighbor before!"
        else seenHash{ neighbor } = 1.

The example above also shows that the syntax of hashes is the same as the syntax for lists when storing or retrieving data. Unlike lists, however, hashes do not hold ordered data, and none of the other list operators work with hashes.

When using hashes with ints, floats, vectors, matrices and strings, then steve will test the equivalence of the key when looking up or storing the data. This means that two equivalent strings, even if they are stored in different variables, will refer to the same value in the hash. For the other types (objects, pointers, data, lists and hashes themselves), the hash will only return the same value for the same exact variable key. This means that two different lists, even if they contain "equal" data, will access different values in the hash.

An important feature of hashes in steve is that they are always passed by reference and are not copied. This means that if you pass a hash to a function, then any modifications done to the hash inside the function will modify the original hash.

hash Operators

A list of the keys in a hash may be retrieved using the built-in function keys. This key list is often used to iterate through the items in a hash:

foreach key in keys( myHash ): {
        print myHash{ key }.
}

Conversion to Other Types

hashes cannot be converted to any other types.

The pointer Type

[Note] For developer use only

The pointer type is for use by breve and plugin developers only.

pointer variables store C-style pointers to internal data. They are not used for writing simulations in steve and are only used by breve developers and plugin authors.

pointer variables are only useful in the context of interacting with internal C-style function calls: they do not contain methods, variables or any other meaning in the context of most steve code. Like objects, however, pointers can be tested to see if they are NULL (0), but cannot be used in mathematical expressions. That is to say that pointers have a meaning in a boolean context of control structures such as if and while (as well as the logical operators && and ||).

Copying a pointer (assigning it to another variable), as in C, will not copy the data is points to.

Conversion to Other Types

pointers cannot be converted to any other types.

The data Type

[Note] For developer use only

The data type is for use by breve and plugin developers only.

data variables are similar to pointer variables in that they contain a reference to internal data. Also like pointer variables, they are not to be used in regular simulation code—they are only to be used by breve developers and custom plugins.

The different between data and pointer is that data refers to a linear block of internal data of known size. This means that data variables can be successfully archived, while pointers cannot. The only use for data variables is archiving and dearchiving internal data. For more information on using the data type with plugins, see the section on Archiving Plugin Data With The data Type (the section called “Archiving Plugin Data With The data Type”).