BlitzMax/Language
From Wikibooks, the open-content textbooks collection
Contents |
[edit] Syntax
[edit] Variables
Variables are used to store values that change during the execution of your program.
Variables should be declared in your program before use. Declaring a variable means defining a name and type for the variable and, optionally, an initial value.
The general syntax for declaring a variable is: Identifier:Type=Expression
Multiple variables may be declared in one statement using the comma separator.
If the type of a variable is omitted, the variable defaults to being of type Int. If the initial value expression is omitted, the variable is assigned an initial value of Null.
There are 3 kinds of variable, each of which differs by how and where the variable is stored:
[edit] Local Variables
Local variables are used to store temporary values that will eventually be discarded. Local variables are associated with the block of code they are declared in, and are only visible to code within that block. A block of code is represented by one of the following:
- The body of a function or loop
- The body of an if/then/else statement
- The body of a case or default statement
To declare a local variable, use the Local keyword:
Local int_var Local string_var:String="Str",float_var:Float=10.5
You should prefer the use of local variables, as they are the fastest to use.
[edit] Global Variables
Global variables are variables that exist for the entire lifetime of a program.
To declare a global variable, use the Global keyword:
Global int_var Global string_var:String="Str",float_var:Float=10.5
[edit] Field Variables
Field variables are declared within user-defined types using the Field keyword:
Type Foo Field int_var Field string_var:String="Str",float_var:Float=10.5 End Type
See Classes and Objects for more on field variables.
[edit] Assigning variables
Once declared, a variable's value may be changed using an assignment statement: Variable=Expression. You can also perform 'modifying' assignments, which are shorthand for Variable=Variable Operator Expression. The syntax for modifying assignments is:
| Syntax | Operator |
|---|---|
| :+ | Addition |
| :- | Subtraction |
| :* | Multiplication |
| :/ | Division |
| :Mod | Remainder |
| :& | Bitwise and |
| :| | Bitwise or |
| :~ | Bitwise exclusive or |
| :Shl | Bitwise shift-left |
| :Shr | Bitwise shift-right |
| :Sar | Bitwise arithmetic shift-right |
For example, the code my_var:+1 can be used in place of my_var=my_var+1.
[edit] Data Types
The following data types are possible for variables:
| Syntax | Description | Tag |
| Byte | 8 bit unsigned integer | @ |
| Short | 16 bit unsigned integer | @@ |
| Int | 32 bit signed integer | % |
| Long | 64 bit signed integer | %% |
| Float | 32 bit floating point | # |
| Double | 64 bit floating point | ! |
| String | 16 bit unicode string | $ |
| ElementType[] | Array with elements of ElementType | |
| TypeName | Object of the type specified | |
| ReturnType(Parameters) | Function | |
| VariableType Ptr | Pointer to a variable | |
| VariableType Var | Variable |
Int is used, when data type is omitted, except in SuperStrict mode, where data type must always be specified.
[edit] Automatic Conversions
BlitzMax performs the following conversions automatically:
| Source Type | Target Type |
| Short | Int, Long, Float, Double, String |
| Int | Short, Long, Float, Double, String |
| Long | Short, Int, Float, Double, String |
| Float | Short, Int, Long, Double, String |
| Double | Short, Int, Long, Float, String |
| Object | Base object |
| Object | Byte Ptr |
| Array | Byte Ptr, ElementType Ptr |
| Function | Byte Ptr |
| Pointer | Byte Ptr |
[edit] Casting
Type conversions may also be done manually using casting. Type conversions that are not done automatically need to be done manually before eg. variable assignment. The syntax for casting is DataType(Expression):
Print(String(1)+String(2)) ' This prints "12", because strings, not integers, are added.
In addition to the conversions handled automatically, the following conversions can be done using casting.
| Source Type | Target Type |
| String | Short, Int, Long, Float, Double |
| Object | Derived object |
| Integer | Pointer |
| Pointer | Integer |
| Pointer | Pointer |
[edit] Expressions
[edit] Functions
[edit] Control Structures
[edit] Loops
[edit] For
For To Step - Next
This is the for loop found traditionally in Basic (and other languages). The loop increments a variable as specified and exits once the variable is greater that the 'to' value. The example code below is executed five times with i values 2, 4, 6, 8 and 10.
For i = 2 To 10 Step 2 Print "Number"+i Next
For Until Step - Next
The difference to a 'to' loop is that once the variable becomes equal to the 'until' value, the loop is exited. So the code below only executes 4 times.
For i = 2 Until 10 Step 2 Print "Number"+i Next
For EachIn - Next
EachIn loops are used with objects that provide the necessary methods. Examples in the standard modules are arrays and linked lists. The following code prints all values in the array.
Local arr[] = [1,2,3,10] For val = EachIn arr Print "Value"+val Next
[edit] While
A while loop evaluates an expression at the start of each loop, and repeats as long as the expression is true. The following code waits for escape key.
While Not KeyDown(KEY_ESCAPE) 'Do nothing Wend
[edit] Repeat
Repeat - Until
A repeat loop always executes at least once. The expression is evaluates at the end of each loop, and the loop exits when the expression becomes true. The example code also waits for escape key, but always executes at least once.
Repeat 'Do nothing Until KeyDown(KEY_ESCAPE)
Repeat - Forever
This loop executes forever - or, more often, until either End, or Exit is called.
Repeat If KeyDown(KEY_ESCAPE) Then Exit Forever
[edit] Exit and Continue
Exit will prematurely exit out of any loop.
Continue will restart to the top of any loop.
Example:
Local foobar:Int
For foobar = 0 To 10
If foobar = 2
' Go back to the beginning of the loop
' The action of the For..Next loop still executes, so foobar will be 3)
Continue
End If
If foobar = 7
' Exit the loop prematurely
Exit
End If
Print("foobar=" + foobar + "!")
Next
[edit] If
One-liners:
- If Condition Then Statements Else Statements
- If Condition Then Statements ElseIf Condition Then Statements Else Statements
Expanded:
- If Condition Then
- Statements
- Else If Condition Then
- Statements
- Else
- Statements
- End If
In either form, Then is entirely optional.
Examples:
Local foobar:Int = 10
If foobar = 10 Then Print("foobar = 10!") Else If foobar = 11 Then Print("foobar = 11!") Else Print("foobar = " + foobar + "!")
If foobar = 10 Then
Print("foobar = 10!")
Else If foobar = 11 Then
Print("foobar = 11!")
Else
Print("foobar = " + foobar + "!")
End If
[edit] Select/Case
A Select/Case block allows you to simplify complex conditional tests.
The select expression is compared with each of the case expressions and, if found to be equal, the code within the appropriate case block is executed.
If no matching case is found, the code within the optional Default block is executed.
Structure:
- Select Expression
- Case Expressions
- Statements
- Default
- Statements
- Case Expressions
- End Select
Example:
Local foobar:Int = 10
Select foobar
Case 10
Print("foobar = 10!")
Case 11
Print("foobar = 11!")
Default
Print("foobar = " + foobar + "!")
End Select
[edit] Classes and Objects
[edit] Type
[edit] Object
[edit] Strings
[edit] Arrays
Arrays are used to store sequences of variables, or 'elements'. An element within an array is accessed by 'indexing' the array with an integer offset. The general syntax for indexing an array is: Array[Index1,Index2 etc...]
In BlitzMax arrays, like strings, are objects, and have methods.
[edit] Creating Arrays
The most common way to create an array is when declaring a variable:
Local int_array[10]
This will initialize the int_array variable with a 10 element array. You can declare an 'empty' array by using []:
Local int_array[]
An empty array is identical to an array with 0 elements.
Something to remember about arrays is that, unlike in earlier versions of BlitzBasic, they are zero based. That is, the first element of the array has an index of 0. So if you declare an array with 4 elements, they will be indexed from 0 to 3.
Local int_array[4] 'Create an array with 4 elements (the default type for the array will be Int) int_array[0] = 1 'put the number 1 in the first element of the array. int_array[1] = 2 'put the number 2 in the second element of the array. int_array[2] = 3 'put the number 3 in the third element of the array. int_array[3] = 4 'put the number 4 in the fourth element of the array. print int_array[0] 'print the first element print int_array[3] 'print the fourth element
Arrays may also be created 'on the fly' using the syntax: New ElementType[Dimension1,Dimension2 etc...] This returns an array of the specified dimension(s) with each element initialized to Null. For example:
Local int_array:Int[] int_array=New Int[10]
[edit] Auto Arrays
'Auto arrays' are simply arrays with predefined values in each index. They may be created using the syntax [Element1,Element2 etc...]. This returns a 1 dimensional array containing the specified elements, for example:
Local int_array[]=[1,2,3,4,5]
Each element of an auto array must have exactly the same type. If necessary, you can use type conversions to enforce this.
[edit] Copying and Resizing
Since arrays are really objects, the following code will not copy the array. It only creates another variable that points to the same object.
Local arr:Int[] = [1,2,3] Local arr2:Int[] = arr
To copy an array, you must use slices. The syntax for slicing is array[from..to].Both from and to may be omitted; they default to 0 and the last index, respectively. Copying the array is simple:
Local arr2:Int[] = arr[..]
Resizing an array using slices:
Local myArray[10] 'Create an array with 10 elements (0..9) myArray = myArray[..20] 'Increase number of elements in the array to 20 myArray = myArray[..5] 'Take the first 5 elements
Note that you cannot use slices with multi-dimensional arrays.
[edit] Resizing an Array of Arrays
Warning: this is a slightly advanced topic likely to confuse beginners.
Although you cannot resize normal Multi-Dimensional Arrays, you can resize an Array of Arrays (that being a 1D array where each element is a 1D array).
You first need to resize the main array and then loop through each element in it and resize the arrays that they contain.
Example:
Local x :Int[][] 'Create our array of arrays x = x[ .. 5 ] 'resize the main array to have 5 elements 'loop through each new element in this array 'and resize the arrays that they contain For l = 0 Until Len( X ) x[ l ] = X[ l ][ .. 5 ] Next
If you were to view the array it might look something like this:
x[0][0,0,0,0,0] x[1][0,0,0,0,0] x[2][0,0,0,0,0] x[3][0,0,0,0,0] x[4][0,0,0,0,0]
[edit] Multi-Dimensional Arrays
To create an array with more than one dimension, you can specify indexes separated by commas:
Local int_array1 : Int[4,4] 'create a 4x4 array Local int_array2 : Int[3,3,3] 'create a 3x3x3 array
You can then refer to them like so:
int_array1[0,0] = 100 int_array2[2,1,0] = 1000
[edit] Multi-Dimensional Auto Arrays
This is a slightly more advanced topic and as such, beginners may at first find it confusing.
It is not currently possible to create normal Multi-Dimensional Arrays AND auto-initialize them. You can however cheat a little:
Local string_array:String[][] = [["Bob","Kate","Percy"],["Cecil","Edmund","Elizabeth"]] Print string_array[0][2] 'this will print Percy Print string_array[1][0] 'this will print Cecil
What the above actually does is create an Array of type String Array. If you were to attempt to refer to it in the conventional manner it would cause an error (Incorrect number of array dimensions).
Local string_array:String[][] = [["Bob","Kate","Percy"],["Cecil","Edmund","Elizabeth"]] Print string_array[0,0] 'this line would cause an error
[edit] Arrays in Types
If you wish to place an array in a type you must initialize them using New before you can use it. You can not declare the size of the array on the line after Field. For now you actually can directly declare the size of a Field array. Could not do that for Type Globals though. ( So someone could perhaps sort out this article. Might do that myself should an opportunity rise. )
Type MyType
Field arr:Int[] ' Not initialized
End Type
Local a_type = New MyType
a_type.arr = New Int[32] ' Initialize the array to 32 elements
To make things easier for yourself you can create the array inside the type's New method.
Type MyType
Field arr:Int[] ' Not initialized
Method New() ' This function is called when a new MyType is created with New
arr = New Int[32]
End Method
End Type
Local a_type = New MyType ' No need to initialize the array
You can also do this to multi-dimensional arrays. Just put commas between the brackets.
Type MyType
Field arr:Int[,,] ' Not initialized
Method New() ' This function is called when a new MyType is created with New
arr = New Int[10,10,10]
End Method
End Type
Local a_type = New MyType ' No need to initialize the array
[edit] Array Methods
Arrays provide a Sort method, a Dimensions method and a read only length field. In addition they provide some undocumented methods, which are not meant to be used, and may change at any time.
Sort
Sort takes an optional ascending parameter that defaults to true. Here is an example of sorting an array:
Strict
Local arr:String[]=["some","random","strings","in","a","string","array"]
arr.Sort 'sort ascending
Print "Array in ascending order..."
For Local t:String=EachIn arr
Print t
Next
arr.Sort False 'sort descending
Print "Array in descending order..."
For Local t:String=EachIn arr
Print t
Next
Dimensions
Returns an int array with array dimensions. So for example Int[10,5].Dimensions() would return Int[2] equal to the auto array [10,5].
The following methods are undocumented and as such, are subject to change without notice. They may still be useful.
| numberOfDimensions | Returns an Int value indicating the number of dimensions in the array. |
| elementTypeEncoding | Is a Byte Ptr to a value representing the data type of the array elements.
Returned Values Const TYPE_BYTE = 98 Const TYPE_SHORT = 115 Const TYPE_INT = 105 Const TYPE_FLOAT = 102 Const TYPE_LONG = 108 Const TYPE_DOUBLE = 100 Const TYPE_STRING = 36 Const TYPE_OBJECT = 58 Const TYPE_ARRAY = 91 Const TYPE_POINTER = 42 |
| sizeMinusHeader | Returns an Int value. |
This returns the number of elements * 4.
Local a:Int[2,2,2] Print a.numberOfDimensions 'Prints 3 Print a.elementTypeEncoding[0] 'Prints 105 if Int, 102 if Float, 36 if String Print a.sizeMinusHeader
[edit] Iterating through each element of an array
If you want to loop through each element of an array you can use a For-EachIn loop:
'create a 10 element array and pre-initialize the values Global myArray:Int[] = [0,1,2,3,4,5,6,7,8,9] For Local i:Int = EachIn myArray 'print the int contained in each array element Print i Next
This is all very well, but what if you want to only loop through a portion of them? Say for instance, the last five. Well for that, you need a slice like so:
'create a 10 element array and pre-initialize the values Global myArray:Int[] = [0,1,2,3,4,5,6,7,8,9] 'loop through each element starting with the sixth element (0 based array index) For Local i:Int = EachIn myArray[5..] 'print the int contained in each array element Print i Next
[edit] Exceptions
BlitzMax provides a mechanism for handling runtime errors known as exception handling.
An exception is actually just an object. You can throw and catch exceptions using the Throw command and a Try/Catch block. Here is a simple example:
Function ExTest() Throw "Bingo!" End Function Try ExTest() Catch ex:Object Print ex.ToString() End Try
Throwing an exception causes the program to jump to nearest Catch block. You can provide multiple catch blocks for catching exceptions of different types. If there is no Catch block, then the exception is sent to the debugger which usually has the effect of halting the program with an appropriate message.
Exception objects should implement the ToString method of Object to provide a textual description of the exception.
BlitzMax has several built-in exception types, all of which extend TBlitzException. These are:
| Exception | Cause |
|---|---|
| TNullObjectException | Thrown when a program attempts to access a null object |
| TNullMethodException | Thrown when a program attempts to call an abstract method |
| TNullFunctionException | Thrown when a program attempts to call a null function |
| TArrayBoundsException | Thrown when a program attempts to access an array element outside of an array's bounds |
| TRuntimeException | Thrown by the RuntimeError or Assert commands |
[edit] Pointers
Pointers are intended for use by code that must perform low level interaction with the operating system and/or speed sensitive code. Pointers are not recommended for general use, as misuse of pointers can easily result in memory corruption causing all sorts of bugs and headaches!
Pointers are declared by appending Ptr to the type of a variable or function parameter declaration:
Local int_ptr:Int Ptr
The VarPtr operator allows you to find the address of a variable, yielding a pointer:
Local an_int=10 int_ptr=VarPtr an_int
Array style indexing is used to dereference pointers:
Print int_ptr[0]
BlitzMax also supports pointer arithmetic, using the standard + and - operators.