An int
is a whole number, identical to the
int
type in C.
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
|.
A real number, also
known as "double", identical to the double
type in C. Internally, floats are represented
by 8-byte doubles.
An
object
is an instance of a steve class.
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”).
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.
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).
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.
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.
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.
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.
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
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.
The following operations can be used with list
expressions:
insert
: inserts
expression
, at list
, { index
}expression
at the
specified index in the list, shifting up other list elements with
higher indices
remove
: removes the
element of list
, { index
}list
at the
specified index and returns it, shifting down other list elements
with higher indices
push
: appends expression
, onto list
expression
onto the end of list
pop
: removes the last
element of list
list
and
returns it
prepend
: prepends expression
, onto list
expression
onto the start of
list
unprepend
: removes the first
element of list
list
and
returns it
: 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
}
: 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.
list
, { expression
, } = value
sort
: sorts
list
, with method-name
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
: 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.
list
|
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 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".
The following operations can be done one strings:
: returns, as a
string, the letter at the specified index.
string
{ index
}
: replaces the
letter at the specified location with the string string
{ index
} = otherString
otherString
.
|
: returns the
length of the string.
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".
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.
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.
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 }. }
![]() | For developer use only |
---|---|
The
|
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.
![]() | For developer use only |
---|---|
The |
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”).