Introducing wxBasic
wxb is a cross-platform BASIC interpreter licensed under the LGPL. While not complying with the ANSI BASIC standard, wxBasic provides much of the functionality associated with modern structured BASIC, along with a number of extentions borrowed from languages such as Python, Lua and Java.

At its core, wxBasic is a fairly small language, weighing in at under 300K (less than 80K when compressed via UPX). However, wxBasic gains much of its functionality by using the wxWidgets library, which provides a cross-platform GUI and non-GUI functionality. The wxWidgets-enabled version of wxBasic is far more capable, but quite a bit heftier.

How wxBasic Differs from Other Basics
wxb has a mixed parentage, deriving mostly from QBasic, but pilfering from C, Lua, Python, and VB.NET. The result is a language with a lot of 'C-isms'. The main points where wxBasic differs from 'classic' BASICs is:

Simple Datatypes Not Passed by Reference
Some datatypes (like Arrays and Objects) are passed to routines by reference, but the "simple" datatypes (such as Number and String) are not. This means that if you change the parameter for simple datatypes, you won't change the parameter in the caller. For example:

   Sub foo( a )
      a = a + 10
      Print "In foo(), a ="; a
   End Sub

   b = 100
   Print "Before calling foo(), b ="; b
   foo( b )
   Print "After calling foo(), b ="; b

In some versions of Basic, changing the value of a would change the value of b. This isn't the case in wxb. If you want to change the value of b, you need to assign the value back:

   Function foo( a )
      a = a + 10
      Print "In foo(), a ="; a
   End Function

   b = 100
   Print "Before calling foo(), b ="; b
   b = foo( b )
   Print "After calling foo(), b ="; b

Functions Return Values via the RETURN Keyword
To return a value from a function in wxb, you need to use the Return keyword. It works the same way return works in C: the function exits at that point, and returns the values that follow the Return statement:

   Function foo( a )
      Return a * 10
   End Function

If you want to continue processing through the function, just store the value in a temporary variable:

   Function foo( a )
      Dim tmp = a * 10
      ' Do something else
      Return tmp
   End Function

Functions Can Return Multiple Values
Like Lua and Python, wxb allows functions to return multiple values. For example:

   Function doubleTheValue( a )
      ' Return double the value and original value
      Return a*2, a
   End Function

   newValue, oldValue = doubleTheValue( 120 )

Basically, this replaces the need for passing values by reference. wxb checks to make sure the number of arguments on both sides match. If they don't, wxb will fill in the missing values on the left hand side with Nothing, or drop extra values on the right hand side. For example:

   a, b = 10, 20, 30

will cause a to be assigned the value 10, and b the value 20. There is no variable to recieve the value 30, so it is dropped. Similarly:

   a, b = 10

will cause a to be assigned the value 10, and b the value Nothing.

If a function doesn't explicitly return a value, it will by default return the value Nothing:

   Function doNothing()
   End Function

   a = doNothing()

This will cause the variable a to be assigned the value Nothing.

Functions Can Have Optional Parameters
You can specify that a routine can have optional parameters. If the routine is called without these parameters being passed, they will be set to their default values. For example:

   Sub hasOptionalParms( a, b, c = 10, d = 100 )
      Print a, b, c, d
   End Sub

Functions Can Have Variable Numbers of Parameters
You can specify that a routine will take a number of (unnamed) parameters, similar to C's printf command:

   Sub hasVariableParms( a, b, ... )
FIXME!!!

Dynamic Variable Declaration
In wxb, it is not necessary to declare variables or their type; they will be created "on the fly":

   aString = "This is a string"
   aNumber = 123

Variables declared outside of routines are automatically global in scope:

   globalVar = "I'm a global variable"

   Sub foo()
      localVar = "I'm a local variable"

      ' This references the global variable globalVar
      Print globalVar

      ' This references the local variable localVar
      Print localVar

   End Sub

As convenient as this option is, it's much safer to require variables to be explicitly declared in wxb. This is done by adding the statement:

   Option Explicit

With Option Explicit enabled, you will need to explicitly declare your variables before use:

   Dim globalVar = "I'm a global variable"

   Sub foo()
      Dim localVar = "I'm a local variable"

      ' This references the global variable globalVar
      Print globalVar

      ' This references the local variable localVar
      Print localVar

   End Sub

No Need To Declare Forward References
wxb will automatically resolve all forward references.

Case Insensitive
The first version of wxb was case sensitive, but this is no longer true.

Datatypes
All values in wxb are stored as Variants. However, the variant will be one of the following types:

•	Variant
•	Nothing
•	Integer
•	Number
•	String
•	DateTime
•	Object
•	Routine
•	Array
•	Table
•	List

These value have common properties:

	integer = variant.GetType()
	string = variant.ToString()
	integer variant.Equal( otherValue )
	integer variant.Compare( otherValue )
	clone = variant.Clone()

However, not all datatypes implement these properties.

Nothing
Nothing is akin to other language's nil or null value. In a truth test, it evaluates to False. All unassigned variables default to Nothing, even if they have been declared as some other type. You can directly test for a value of Nothing:

   If a = Nothing Then
      Print "a = Nothing"
   End If

It implements the following methods:

	isNumeric
	fromChar
	toChar
	isTrue

Integer
Integer is a integer. It is stored as an int value, although all math operations are internally done with double, even if both types are declared as Integer.

Number
Number is a floating point number, stored as a C double. All math operations in wxb are internally done with a Number type, even if the datatype is declared differently.

String
String is an alphanumeric string. When tested in a truth operation, an empty string returns False, and a non-empty string returns True.
You can embed special characters into the string by using the backslash (\)

	\n	newline
	\r	carriage return
	\t	tab
	\'	single quote (not really needed)
	\"	double quote
	\\	backslash

For example:

   stringWithANewline = "This is the first line\nThis is the second"

You can treat a string as if it were a collection. You iterate through a string. For example:

   For Each position, letter In "Hello, World"
      Print "Position="; position, "Letter="; letter
   End For

You can also index and slice a string like an array. For example:

   Print "Hello, World"[8]

prints "W", and:

   Print "Hello, World"[1:5]

prints "Hello".

DateTime
DateTime represents a date and time. It is normally created by calling the routine TimeValue:

   Dim myDate = TimeValue( "Jan 12, 2003" )

You can extract the parts of the date by calling the various methods (also available as builtin functions):

   myDate.Year()
   myDate.Month()
   myDate.MonthName()
   myDate.Weekday()
   myDate.Day()
   myDate.DayName()
   myDate.Hour()
   myDate.Minute()
   myDate.Second()

DateTime values can be compares for exact equality or inequality. To determine specific differences between dates, use DateDiff (see the DateDiff function for details).

Object
Any data declared with a Class (builtin or user declared) is stored as a datatype Object. Objects are passed by reference, not by value. If you want to create a unique copy of an Object, use the Clone method:

   myCopy = theObject.Clone()

Objects are reference counted, and automatically destroyed when no object refers to them anymore. For more information about objects, see the section on Classes.

Routine
A Routine is a user-defined routine or method. There is currently only an internal datatype.

Collections
A collection is a grouping of Variant data which can be accessed by a key value. For example, Arrays, Tables, and Lists are all collections. There are operations that are (in general) common across collections. You can access an element in a collection by specifying that element's key. For example, here's a Table collection:

   Dim myCats = {}

Indexes
Let's populate the Table:

   myCats[ 1 ] = "Chester"
   myCats[ 2 ] = "Charlotte"
   myCats[ 3 ] = "Chloe"

If we print the table:

   Print myTable

we'll get: { 1:"Chester", 2:"Charlotte", 3:"Chloe" }

We can access elements in a collection by specifying the collection, and the key in square brackets:

   Print myCats[ 3 ]

prints "Chloe".

Slices
If the collection is ordered, you can print a slice from the collection:

   Print myCats[ 2:3 ]

prints { 2:"Charlotte", 3:"Chloe" }

Collection Methods
In addition to the methods implemented by Variants, most collections implement one or more of these methods:

	collection.Append( value )
	collection.Prepend( value )
	collection.InsertAt( key, value )
	collection.Slice( startSlice, endSlice )
	integer = collection.Count

Array
An Array is a collection of static size. Like all other collections, they are passed by reference. Unlike most versions of Basic, wxb uses square brackets to help distinguish them from routine calls. Here's a simple declaration:

   Dim myArray[10]

If the lower range is not declared, wxb will assume the array starts at zero. You can have up to five dimensions to the array:

   Dim myArray[5 To 20, -10 To 10]

Array with undeclared types values initialize their values to zero. You can specify an initial value like this:

      Dim myArray[10] = Nothing

You can declare the type as well:

      Dim myArray[10] As Number

You can also declare the type and initial value:

   Dim myaArray[10] As Integer = 10

Table
An Table is an unordered collection of dynamic size. Like all other collections, they are passed by reference. You create a table by declaring a collection within curly brackets. The following declares an empty Table:

   Dim myTable = {}

A collection is indexed by keys, which can either be Integer or String values (Numbers will be automatically converted to Integers). For example:

   Dim myCats = { 1:"Chester", 2:"Charlotte", 3:"Chloe", 4:"Julius" }

is the same as writing:

   Dim myCats = {}
   myCats[1] = "Chester"
   myCats[2] = "Charlotte"
   myCats[3] = "Chloe"
   myCats[4] = "Julius"

Note here that if the key does not exist in the List, wxb will insert a new key/value pair. 

If you leave off the key in the declaration, wxb will assign a sequential value, so this produces the same result as the prior example:

   Dim myCats = { "Chester", "Charlotte", "Chloe", "Julius" }

You can retrieve data by specifying the index, the same as an array:

   Print myCats[1]

If a key does not exist in the Table, wxb returns the value Nothing. If a List contains another List, you can access it as if it were an array:

   Dim myCats = {}
   myKids[ "Chester", "favorite food" ] = "Pounce"

is the same as writing:

   Dim myCats = {}
   myKids[ "Chester" ] = { "favorite food":"Pounce" }

which is also the same as:

   Dim myCats = { "Chester":{ "favorite food":"Pounce" } }

and it can be accessed similarly:

   Print myKids[ "Chester", "favorite food" ]

prints "Pounce".

As with the other collections, you can iterate through it with the For Each loop:

   For Each index, name In myCats
      Print index, name
   End For

Note that the List is unordered, so there is no guarantee that the data will come back in any order.

You can remove items from the list by removing the key from the collection:

   myCats.Remove( "Julius" )

List
An List is an ordered collection of dynamic size. Like all other collections, they are passed by reference. You create a table by declaring a collection within square brackets. The following declares an empty List:

   Dim myList = [] 

Construction of a Table is similar to that of a list, except that the keys are implicit, based on order:

   Dim myCats = [ "Chester", "Charlotte", "Chloe", "Julius" ]

You can add items to the list with Append, which adds the elements to the end of the list:

   Dim myCats = []
   myCats.Append( "Chester" )
   myCats.Append( "Charlotte" )
   myCats.Append( "Chloe" )
   myCats.Append( "Julius" )

Or with Prepend, which adds elements to the beginning:

   Dim myCats = []
   myCats.Prepend( "Julius" )
   myCats.Prepend( "Chloe" )
   myCats.Prepend( "Charlotte" )
   myCats.Prepend( "Chester" )

Or Insert, which specifies a position to insert at:

   Dim myCats = []
   myCats.Insert( 1, "Julius" )
   myCats.Insert( 2, "Chloe" )
   myCats.Insert( 3, "Charlotte" )
   myCats.Insert( 4, "Chester" )

Elements can be accessed by index, starting at 1. Attempting to access a non-existant element will result in wxb throwing an error.

   Print myCats[3]

You can also access a slice of elements:

   Print myCats[2:3]

wxBasic Syntax

Assignment
	lval {, lval} = expr {, expr }

Assigns a value to one or more lval:

	a, b, c = 1, 2, 3

CLASS
	CLASS className [INHERITS className]
		[DIM attribute {, attribute}]
		subroutineDefinition
		functionDefintition
	END CLASS

Creates a new user-defined class. Single inheritance is supported. Class attributes are defined in the Dim section. 

New instances of a class object are created by calling a constructor method with the same name of the class. For example:

	‘ create a Point class
CLASS Point
		DIM x, y
	END CLASS

	‘ create a point
	p = Point()
	p.x = 10
	p.y = 20

Objects are automatically destroyed when there are no references to the object. If you want an object to be permanent, create it with the New keyword:

	‘ create a Point class
	CLASS Point
		DIM x, y
	END CLASS

	‘ create a temporary point and assign some values
	p1 = Point()
	p1.x, p1.y = 10, 20

	‘ create a permanent point and assign some values
	p2 = NEW Point()
	p2.x, p2.y = 40, 80

	‘ destroy the temporary point
	p1 = NOTHING

	‘ This does not destroy the permanent point
	p2 = NOTHING

To destroy an object created with New, use the Dispose command:

	‘ Destroy the point
	DISPOSE p2

You can define an initializer for a class by including a NEW method in the class:

‘ create a Point class
CLASS Point
	DIM x, y

	SUB NEW ( useX, useY )
		x, y = useX, useY
	END SUB
	END CLASS

	‘ create a Point
	p1 = Point( 10, 20 )

When an object is destroyed, the FINALIZE routine for it is run:

‘ create a Point class
CLASS Point
	DIM x, y

	SUB NEW ( useX, useY )
		x, y = useX, useY
		PRINT “Created Point {“; x; “, “; y; “)”
	END SUB

	SUB FINALIZE()
		PRINT “Destroyed the point {“; x; “, “; y; “)”
	END SUB
	END CLASS

CLOSE
	CLOSE
	CLOSE #handle

Close a currently open file. To close all files, use Close without a handle number.

	‘ Append text to a file, and then close it
	OPEN “tmp.txt” FOR APPEND AS #1
	PRINT #1, “Some text”
	CLOSE #1

Also see fClose.

CONST
CONSTANT
	CONST constantName = expression {, constantName = expression }
CONSTANT constantName = expression {, constantName = expression }

Declare a variable to be a constant. Constants are similar to variables, except they cannot be assigned values.

	‘ Declare the name of the program
CONST ProgName = “My Cool Program”,
	Version = “1.0”

DIM
	DIM name [ '[' [expr [TO expr] ']' ] [ = expr] [AS type]
		(, name [= expr] }

Define an object. Arrays can be initialized to a default value by assiging them. Variables that are unassigned default to NOTHING.
	
	' Create a 2 x 3 array, initialize it to zero
	DIM a[2,3] = 0

	' Create a string variable and assign it
	DIM b AS STRING = "This is a string"

	' Create and assign several variables
	DIM a = 10, b, c = a+12

END
	END

Halt the program.

	‘ Stop the program if the user is bored.
	INPUT “Do you want to play again (Y/N}?”; answer
	IF answer = “Y” OR answer = “y” THEN
		END
	END IF

FOR...NEXT
	FOR variable = startExpr TO endExpr {STEP stepExpr}
		[CONTINUE]
		[BREAK]
		[EXIT FOR]
		{ statement }
	ELSE
		{ statement }
	END FOR | NEXT {variable}

Loop from startExpr to endExpr, incrementing by stepExpr. If stepExpr is left off, it is assumed to be 1. BREAK leaves the loop immediately, while CONTINUE jumps to the top of the loop for the next value.

Here is an example of a loop printing the numbers between 1 and 10, inclusive:

	' loop from 1 to 10
	FOR i = 1 TO 10
		PRINT i
	NEXT

If the loop is not exited via the BREAK statement, the ELSE clause will execute.

	' loop through an array, looking for a value
	FOR i = 1 to LENGTH( list )
		IF list[i] = someValue THEN
			PRINT "Found it!"
			BREAK
		END IF
	ELSE
		PRINT "Didn't find it"
	END FOR

FOR EACH...END FOR
	FOR EACH variable {, variable} IN expression
		[CONTINUE]
		[BREAK]
		[EXIT FOR]
		{ statement }
	ELSE
		{ statement }
	END FOR
		
Iterate through a collection (table, list). If only one loop variable is used, it will hold the index from the collection. If two variables are used, they will hold the key/index and value. CONTINUE, BREAK and ELSE behave the same as a FOR loop.

	' Print the value and keys from a list
	FOR EACH key, value IN list
		PRINT key, value
	END FOR

FUNCTION ... END FUNCTION
	FUNCTION name ( [arg [= expr]{,arg [= expr]} ] [, ...] )
		[ DIM variable {, variable } ]
		[ STATIC variable {, variable } ]
		[ SHARED variable {, variable } ]
		[ RETURN expr {, expr} ]
		[ EXIT FUNCTION ]
		{ statement }
	END FUNCTION

Define a function. Unlike many BASICs, more than one value may be returned from a function. As a result, the Return keyword is used to return values from functions. If no value is explicitly returned, the value Nothing is returned.

	FUNCTION addOne( n )
		RETURN n + 1
	END FUNCTION

You can have optional values in parameters. If these parameters are are not included in the function call, they are assigned the default value:

	FUNCTION hasOptional( a, b=10, c=”default string” )
		PRINT “a=”, a
		PRINT “b=”, b
		PRINT “c=”, c
	END FUNCTION

You can use Static variables in functions. These are variables that retain their value. The initial value of Static variables is Nothing:

	FUNCTION accum( n )
		‘ declare result as a STATIC variable
		STATIC result

		‘ first time calling accum?
		IF result = NOTHING THEN
			‘ initialize the result
			result = n
		ELSE
			‘ add value to the result
			result = result + n
		END IF

		‘ return accumulated result
		RETURN result

	END FUNCTION

Some or all of the return values may be discarded by the caller. If a function returns more values than requested, the extra values are discarded. If the function returns less values than expected, the extra variables are assigned the value Nothing:

	FUNCTION returnThreeValues()
		RETURN 1, 2, 3
	END FUNCTION

	‘ ignore all values
	returnThreeValues()

	‘ ignore the last value
	a, b = returnThreeValues

	‘ Nothing is assigned to d
	a, b, c, d = returnThreeValues()

 IF ... ELSEIF ... ELSE ... END IF
	IF expr THEN
		{ statement }
	{ ELSEIF expr THEN
		{ statement } }
	[ ELSE
		{ statement } ]
	END IF

IF performs conditional operations. For example:

	IF 10 > 12 THEN
		PRINT “10 is less than 12”
	END IF

These tests can be chained together with additional ELSEIF tests, which are performed if the prior tests fail. An optional ELSE clause is executed if none of the prior tests were true:

	IF a = 1 THEN
		PRINT “One”
	ELSEIF a = 1 THEN
		PRINT “Two”
	ELSEIF a = 3 THEN
		PRINT “Three”
	ELSE
		PRINT “Too big!”
	END IF

INPUT
	INPUT [ promptString ;] variable

Prompt the user for a value. This routine is only available in the command line (non-GUI) version of wxBasic.

	‘ Get the user’s name
	INPUT “What’s your name”; yourName
	PRINT “Hello, “; yourName

OPEN
	OPEN filename FOR mode AS #handle

Open a file for reading, writing, or appending. This syntax is deprecated, and the function FOpen() is preferred.

The file modes are:

	Input		Read from the file
	Output	Write to the file, destroying prior contents
	Append	Write to a file, leaving prior contents

The handle is a filenumber. You can find the next available handle by calling FreeFile().

Close a file by calling Close # or Fclose(). You can close all open files with Close.

	‘ Copy “source.txt” to “copy.txt”
	OPEN “source.txt” FOR INPUT AS #1
	OPEN “copy.txt” FOR OUTPUT AS #1

	‘ Read the first file, and copy to the second
	WHILE NOT EOF( 1 )
		LINE INPUT #1, text
		PRINT #2, text
	WEND

	‘ Close the files
	CLOSE #1
	CLOSE #2

OPTION
	OPTION optionName

Option allows toggling on various behaviors for the interpreter. 

The only option currently supported is Option Explicit, which will cause wxBasic to generate an error when it encounters a reference to a variable that has not been declared. Without Option Explicit, the variable a will be automatically declared for you:

	‘ Without OPTION EXPLICIT, variables are created “on demand”
	a = 12

However, with Option Explict, the same code will generate an error, since a has not been explicitly declared:

	‘ Generates an error, because it is not declared:
	Option Explicit
	a = 12

With Option Explicit, you must declare all variables before use:

	‘ No error, a is declared before use
	Option Explicit
	Dim a
	a = 12

This is true even for global variables. To use global variables with Option Explicit, use Shared.

PRINT
PRINT #

PRINT { [expr] [,] [;] }
	PRINT # expr { [expr] [,] [;] }

Send the values following the Print statement to the output. Values seperated by semicolons {;} have no spaces between them, while values seperated by commas {,} have a single space placed between them:

PRINT “Hello, world!”
PRINT “a = “; a

The linefeed is automatically placed after the last item, unless it is followed by a semicolon:

‘ this generates a linefeed
PRINT “Hello, world!”

‘ this does not
PRINT “Hello, world”;

Output can be directed to a file by using the Print # form of the command:

‘ open a file for output
OPEN “output.txt” FOR OUTPUT AS #1

‘ print some text
PRINT #1, “This is written to the file”
PRINT #1, “And so is this”

‘ close the file
CLOSE #1

REDO
	REDO

Redo jumps to the top of the loop (similar to Continue), but doesn’t re-evalute the test condition again. Redo can also be used inside a Try statement. This is an easy way to get into an infinite loop if you aren’t careful.

‘ Open a file. On failure, delete temp file and try again.
Try
	‘ Open a file
	Open “test.txt” For Output As #1

‘ Perhaps out of disk space. Can temp file be deleted?
Catch FileExists( “data.tmp” )
	‘ Delete the temp file
	Kill( “data.tmp” )

	‘ Try again
	Redo
End Try

SELECT CASE ... END SELECT

	SELECT CASE expression
	{ CASE caseTest {, caseTest }
		{ statement } }
	[CASE ELSE
		{ statement } ]
	END SELECT

The Select statement is used to perform a series of tests on the same value. Unlike C, only a single Case branch is executed. caseTest is one of the following:

		IS = | <> | < | > | < | >= expr
		expr TO expr
		expr

For example:

	SELECT CASE a
	CASE 1, 3
		PRINT “The value is either 1, or 3”

	CASE 4 TO 6, 8
		PRINT “The value is 4, 5, 6, or 8”

	CASE IS < 12
		PRINT “The value is greater than 12”

	CASE ELSE
		PRINT “The value is something else”

	END SELECT

SHARED
	SHARED variable {, variable }

Declare a variable in a Function or Sub as referring to a global variable of the same name. This prevents Option Explicit from generating an error.

	DIM myGlobalVariable

	FUNCTION myFunction()
		SHARED myGlobalVariable

		PRINT “Value of global is “; myGlobalVariable

	END FUNCTION

STATIC

	STATIC variableName {, variableName }

Declare a variable that is local to a  Function or Sub, but retains it’s value after the routine is called. The initial value of a Static variable is Nothing.

	FUNCTION accum( n )
		‘ declare result as a STATIC variable
		STATIC result

		‘ first time calling accum?
		IF result = NOTHING THEN
			‘ initialize the result
			result = n
		ELSE
			‘ add value to the result
			result = result + n
		END IF

		‘ return accumulated result
		RETURN result

	END FUNCTION

SUB ... END SUB
	SUB name ( [arg [= expr] {, arg [= expr]} ] [, ...] )
		[ DIM variable {, variable } ]
		[ STATIC variable {, variable } ]
		[ SHARED variable {, variable } ]
		[ RETURN ]
		[ EXIT SUB ]
		{ statement }
	END SUB

Sub is essentially the same as Function, but does not return any values. Refer to Function for details.
THROW
	THOW expr

Throw triggers the Try clause that it is embedded in. See Try for details.

TRY ... CATCH ... END TRY

	TRY
		THROW expression
		{ statement }
	
	[ CATCH expr
		{ statement } 
REDO 		]
	[ CATCH | ELSE
		{ statement } 
REDO		]
	[ FINALLY
		{ statement } 
REDO		]
	END TRY

Try catches errors thrown either by wxBasic when an error occurs, or by the application via the Throw statement.

If an error occurs, code jumps to the first Catch statement. If no Catch statement handles the exception, it jumps to the next Try block. A Catch without a test expression matches any thrown error.

To execute the Try block again, call Redo.

The Finally clause is always executed, even if no error occurred. For example:

	‘ attempt to open a file
	TRY
		OPEN “myfile.txt” FOR INPUT AS #1
		PRINT “This is written to the file”
	CATCH
		PRINT “Error printing to the file"
	FINALLY
		CLOSE #1
	END TRY

WHILE ... END WHILE
	WHILE expr
		[ BREAK ]
		[ CONTINUE ]
		[ EXIT WHILE ]
		{ statement }
	[ELSE
		{ statement } ]
	END WHILE | WEND

While repeats a loop until the test conditions are met. Break exits the loop immediately, and Continue jumps to the top of the loop.

If the While statement is exited without executing a Break, the optional Else statement will be executed.

	‘ Search a file for a matching string
	WHILE NOT EOF()
		INPUT #1, text
		IF instr( text, matchingText ) THEN
			PRINT “Found the text”
			BREAK
		END IF
	ELSE
		PRINT “Text not found”
	END WHILE

Expressions
An expression is a combination of one of the following:

		object.methodName( [ expr {, expr } ] )
		object.property
		expr XOR expr
		expr IN expr (not coded yet!)
		expr OR expr
		expr AND expr
		NOT expr
		! expr
		expr = expr
		expr <> expr
		expr != expr
		expr < expr
		expr > expr
		expr <= expr
		expr >= expr
		expr + expr
		expr - expr
		expr & expr
		expr '|' expr
		expr INV expr
		expr ^ expr
		expr * expr
		expr / expr
		expr \ expr
		expr % expr
		expr << expr
		expr >> expr
		( expr )
		+ expr
		- expr
		'{' [expr {, expr }] '}'
		'[' [expr {, expr }] ']'
		NEW className '(' [expr {, expr}] ')'
		className [ '(' [expr {, expr}] ')' ]
		variableName
		constantName
		integer
		float
		string
		NOTHING
		functionName '(' [expr {, expr}] ')'
		THIS
		expr '[' expr {, expr } ']'

The Buillt In Routines

ABS( n )
Returns the absolute value of n.
	
ACOS( n )
Returns the arccos of n.

ARGV( n )
Returns the value of parameter n.

ASC( string )
Returns the ASCII value of the first character in string.
{
ASIN( n )
Returns the arcsin value of n.

ARCTAN( n )
Returns the arctangent value of n.

CHDIR( directoryName )
Not currently implemented

CHR( n )
Returns a string representation of the ASCII value n.

COMMAND( n )
Returns the value of parameter n passed from the command line.

CONCAT( string1, string2 )
Returns string1 joined to string2.

CONNECT( object, [id, ] eventType, routineName )	
	When event is triggered in object, causes routineName to be triggered.

COS( n )
Returns the cosine of n.

DATE()
Returns the current data in MM-DD-YYYY format.

DIR()
Not currently implemented.

DIREXISTS( name )
Not currently implemented.

DISCONNECT( object, [id, ] eventType )	
	Removes any callback for attached to object for eventType. See CONNECT().

EOF( fileHandle )
Returns nonzero if fileHandle is not at the end of the file.

EXP( n )
Returns the exponent of n.

FCLOSE( fileHandle )
Closes fileHandle. Same as CLOSE #fileHandle.

FGETS( fileHandle )
Returns next line of text from fileHandle.

FOPEN( fileName, modeString )
Opens file fileName in “r” (read), “w” (write) or “a” (append) mode.

FPUTS( fileHandle, string )
Write string to fileHandle.

FILEEXISTS( fileName )
Returns nonzero if file exists.

FIX( n )
Truncates fractional number, rounding down towards zero.

FORMAT( formatString, ... )
Not yet implemented.

FRAC( n )
Returns fractional portion of n.

FREEFILE( n )
Returns next free handle number.

GETWXAPP( n )
Not yet implemented.

GETWXHANDLE( handle )
Not yet implemented.

HEX( n )
Returns hexidecimal representation of n.

INDEXES( arrayName )
Returns number of indexes in arrayName.

INSERT( targetString, subString, position )
Not yet implemented.

INSTR( [startPosition, ] searchString, searchForString )
Returns position of searchForStringin searchString, or 0 if not found.

INT( n )
Convert n to a 32 bit integer, truncating fractional portion.

KILL( fileName )
Delete fileName.

LCASE( string )
Returns string in lower case. 

LEFT( string, length )
Returns the length leftmost characters in string.

LEN( string )
LENGTH( string )
Returns the length of string.

LOC( fileHandle )
Returns the position in fileHandle.

LOF( fileHandle )
Returns the length of fileHandle.

LOG( n )
Returns the natural log of n.

LBOUND( arrayName )
Returns the lower bound of arrayName.

LTRIM( string )
Returns string with leftmost whitespace removed.

MAINLOOP( n )
Not yet implemented.

MID( string, startPosition [, length] )
Returns substring from string starting at startPosition for length characters.

MKDIR( directoryName )
Not yet implemented.

NOTBITS( n )
Returns bitwise not of n.

ORBITS( n1, n2 )
Returns bitwise OR of n1and n2.

QUICKSORT( arrayName )
Not yet implemented.

RANDOMIZE( [seed] )
Reseeds random number generator with seed.

READBYTE( fileHandle )
Returns a single byte from fileHandle.

RENAME( oldFileName, newFileName )
Renames oldFileName to newFileName.

REPLACE( [startPosition, ] sourceString, searchForString, replaceWithString )
Returns string with searchForString replaced with replaceWithString.

REVERSE( string )
Returns reversed string.

RIGHT( string, length )
Returns length rightmost characters in string.

RINSTR( searchString, searchForString [, optionalStartPosition] )
Reverse version of Inst, searches from end to start position.

RMDIR( directoryName )
Not yet implemented.

ROUND( n )
Returns n rounded to the nearest integer.

RTRIM( string )
Returns string with whitespace characters removed from right side.

RUN( commandString )
Not yet implemented.

SEEK( handle [, filePosition] )
Returns current file position. If filePosition is specified, seeks to that position.

SIGN( n )
Returns -1 if n is negative, 1 if n is positive, and 0 if n is zero.

SHELL( commandString )
Executes commandString, waits until finished.

SIN( n )
Returns the sin of n.

SPACE( n )
Returns string built of n spaces.

SQR( n )
Returns square root of n.

STR( n )
Returns the string representation of n.

STRF( n )
Returns the string representation of n.

STRING( string, repetitions )
STRING( n, repetitions )
Returns a string with string repeated repetition times.
If value is numeric, converts n to an ASCII value first.
SUBSTR( sourceString, startPosition, endPosition )
Returns substring from sourceString, starting at startPosition to endPosition.

TALLY( [startPosition, ] searchString, searchForString )
Returns number of times searchForString occurs in searchString.

TAN( n )
Returns tangent of given angle in radians.

TIMER()
Returns current timer value.

TIME( n )
Returns current time as string in HH:MM:SS format.

TYPEOF( object )
Returns string with name of object’s datatype.

UBOUND( arrayName, index )
Returns the upper bound of index index in arrayName.
Not yet implemented.

UCASE( string )
Returns string in upper case.

VAL( string )
Returns the numeric value of string.

WRITEBYTE( fileHandle, byte )
Writes a single byte to fileHandle.

XOR( n1, n2 )
Returns bitwise XOR of n1 and n2.

The wxBasic Virtual Machine
This section documents the opcodes used in the wxBasic virtual machine. You can see a listing of opcodes produced by your program by typing:

   wxbasic -list filename

UNDEFINED
	UNDEFINED
This is opcode zero, and will cause the VM to throw an error if it is executed.

NOOP
	NOOP

This is a "no op" opcode. It does nothing, but acts as a placeholder. It's currently never generated by the VM.

TRACE
	TRACE  lineNumber

This opcode is used to keep track of what line in the source file is being executed. If an error is thrown, this is how the VM can display the errant line. Generation of TRACE opcodes can be suppressed by the -notrace command line option.

HALT
	HALT

This opcode causes the VM to halt and the application to end.
 
END
	END

This opcode indicates the end of the main code section has been reached. If the wxWidgets library is linked and there is an active top window, the wxWidgets main loop will be entered. Otherwise, the application will end.

DROP
	DROP n

Drop n items from the stack.

MISSING
	MISSING n

Returns true if parameter n was not passed on the arglist. Used to implement optional parameters.

NOTHING
	NOTHING

Push the value of Nothing onto the stack.

LITERAL
	LITERAL n

Push literal n from the literal table onto the stack.

    W_OP_LITERAL,           /* push a literal onto the stack */
    W_OP_EMPTYSTRING,       /* push an empty string onto the stack */
    W_OP_INTEGER,           /* push following integer onto the stack */

    /* for loop */
    W_OP_FORPREP,           /* set up for loop */
    W_OP_FORPREP1,          /* set up for loop, no step */
    W_OP_FORSTEP,           /* increment for loop */
    W_OP_FORSTEP1,          /* increment for loop by 1 */
    W_OP_FOREACHPREP,       /* for each test */
    W_OP_FOREACHLOOP,       /* for increment for each loop */

    /* routine calls */
    W_OP_ROUTINE,           /* push routine id onto stack */
    W_OP_CALL,              /* call a routine */
    W_OP_RETURN,            /* return from a call */

    /* input/output */
    W_OP_FILECLOSE,         /* close file */
    W_OP_FILECLOSEALL,      /* close all files */
    W_OP_FILEOPEN,          /* open a file */
    W_OP_FILEREAD,          /* read a line from the file */
    W_OP_READ,              /* read from stdin */
    W_OP_REDIRECT,          /* redirect output of print */
    W_OP_STDIO,             /* redirect back to standard i/o */
    W_OP_PRINT,             /* print a value */
    W_OP_PRINTLN,           /* print a linefeed */
    W_OP_PRINTTAB,          /* print with trailing space */
    W_OP_EMITTAB,           /* print a space, no data */
    W_OP_EMITLN,            /* print a linefeed, no data */
    
    /* jumps */
    W_OP_JMP,               /* unconditional jump */
    W_OP_JMPT,              /* jump on true */
    W_OP_JMPF,              /* jump on false */
    W_OP_JMPONT,            /* jump on true, drop if false */
    W_OP_JMPONF,            /* jump on false, drop if true */

    /* subroutines */
    W_OP_JSR,               /* jump to a subroutine */
    W_OP_RET,               /* exit from subroutine */

    /* exception handling */
    W_OP_STARTCATCH,        /* push catch address onto the catch stack */
    W_OP_ENDCATCH,          /* pop catch address off the catch stack, jump */
    W_OP_JMPCATCHF,         /* jump if expression is not exception */
    W_OP_THROW,             /* throw an exception */
    W_OP_RETHROW,           /* pop catch and rethrow current exception */
    W_OP_EXCEPTION,         /* push exception onto stack */

    /* class related */
    W_OP_DTOR,              /* object destructor */
    W_OP_DELETE,            /* delete an object */
    W_OP_VIRTUAL,           /* resolve a virtual method */
    W_OP_MYVIRTUAL,         /* resolve virtual method with Me */
    W_OP_CALLMETHOD,        /* call method with object on stack*/
    W_OP_CALLMYMETHOD,      /* call method belonging to Me */
    W_OP_NEW,               /* call to new */
    W_OP_NEWTEMP,           /* call to new, create on stack */

    /* math ops */
    W_OP_POWER,             /* power */
    W_OP_NEGATE,            /* negate value */
    W_OP_ADD,               /* addition */
    W_OP_SUB,               /* subtraction */
    W_OP_MUL,               /* multiplication */
    W_OP_DIV,               /* division */
    W_OP_IDIV,              /* integer division */
    W_OP_MOD,               /* modulus */
    W_OP_SHL,               /* bitwise left shift */
    W_OP_SHR,               /* bitwise right shift */
    W_OP_INV,               /* inverse */
    W_OP_CONCAT,            /* string concatenation */
    W_OP_OR_BITS,           /* bitwise or */
    W_OP_AND_BITS,          /* bitwise and */
    W_OP_ADD_SET ,          /* increment lval */
    W_OP_SUB_SET ,          /* decrement lval */
    W_OP_MUL_SET ,          /* multiply lval */
    W_OP_DIV_SET ,          /* divide lval */
    W_OP_IDIV_SET ,         /* integer divide lval */
    W_OP_MOD_SET ,          /* mod lval */
    W_OP_CONCAT_SET ,       /* concat lval */
    
    /* tests */
    W_OP_EQ,                /* equality */
    W_OP_NE,                /* inequality */
    W_OP_LT,                /* less than */
    W_OP_LE,                /* less or equal than */
    W_OP_GT,                /* greater than */
    W_OP_GE,                /* greater or equal than */
    W_OP_NOT,               /* logical not */
    W_OP_DUP,               /* duplicate stack value */
    W_OP_AND,               /* logical and */
    W_OP_OR,                /* logical or */
    W_OP_XOR,               /* logical exclusive or */

    /* case tests */
    W_OP_CASERANGE,         /* range of case values */
    W_OP_CASE,              /* case test */

    W_OP_IN,                /* element is in array */

    /* arrays */
    W_OP_CREATEARRAY,       /* create an indexed array */
    W_OP_INITARRAY,         /* create an array with default values */
    W_OP_ERASEARRAY,        /* reset array back to default values */

    /* tables */
    W_OP_CREATETABLE,       /* create a table */
    W_OP_SETLIST,           /* copy items from stack into table */
    W_OP_SETMAP,            /* map keys and values into table */

    /* lists */
    W_OP_CREATELIST,        /* create a list */
    W_OP_GETSLICE,          /* return a slice from a list */
    W_OP_SETSLICE,          /* set a slice in a list */

    /* variables */
    W_OP_FREE,               /* set variable to undefined */

    /* accessing values */
    W_OP_VARIABLE,          /* return pointer to variable */
    W_OP_INDEX,             /* return pointer to value at index position */
    W_OP_PROP,              /* return pointer to property by index */
    W_OP_PROPBYNAME,        /* return pointer to property by name */
    W_OP_ME,                /* return pointer to current object */

    /* modifiers */
    W_OP_GET,               /* put value of pointer onto stack */
    W_OP_SET,               /* store value on stack into pointer */
    W_OP_LVAL,              /* put pointer on stack */
    W_OP_SETTYPE            /* set datatype for variable */
};

/* opcode names */
char *wOpcodeName[] = {
    "UNDEFINED",         /* no such op */
    "NOOP",              /* no op */
    "TRACE",             /* trace */
    "HALT",              /* halt execution */
    "END",               /* end of code */
    "DROP",              /* drop stack item */
    "MISSING",           /* return true if parm not passed in list */
    "NOTHING",           /* push undefined value onto the stack */
    "LITERAL",           /* push a literal onto the stack */
    "EMPTYSTRING",       /* push an empty string onto the stack */
    "INTEGER",           /* push following integer onto the stack */
    "FORPREP",           /* set up for loop */
    "FORPREP1",          /* set up for loop", no step */
    "FORSTEP",           /* increment for loop */
    "FORSTEP1",          /* increment for loop by 1 */
    "FOREACHPREP",       /* for each test */
    "FOREACHLOOP",       /* for increment for each loop */
    "ROUTINE",           /* push routine id onto stack */
    "CALL",              /* call a routine */
    "RETURN",            /* return from a call */
    "FILECLOSE",         /* close file */
    "FILECLOSEALL",      /* close all files */
    "FILEOPEN",          /* open a file */
    "FILEREAD",          /* read a line from the file */
    "READ",              /* read from stdin */
    "REDIRECT",          /* redirect output of print */
    "STDIO",             /* redirect back to standard i/o */
    "PRINT",             /* print a value */
    "PRINTLN",           /* print a linefeed */
    "PRINTTAB",          /* print with trailing space */
    "EMITTAB",           /* print a space", no data */
    "EMITLN",            /* print a linefeed", no data */
    "JMP",               /* unconditional jump */
    "JMPT",              /* jump on true */
    "JMPF",              /* jump on false */
    "JMPONT",            /* jump on true", drop if false */
    "JMPONF",            /* jump on false", drop if true */
    "JSR",               /* jump to a subroutine */
    "RET",               /* exit from subroutine */
    "STARTCATCH",        /* push catch address onto the catch stack */
    "ENDCATCH",          /* pop catch address off the catch stack", jump */
    "JMPCATCHF",         /* jump if expression is not exception */
    "THROW",             /* throw an exception */
    "RETHROW",           /* pop catch and rethrow current exception */
    "EXCEPTION",         /* push exception onto stack */
    "DTOR",              /* object destructor */
    "DELETE",            /* delete an object */
    "VIRTUAL",           /* resolve a virtual method */
    "MYVIRTUAL",         /* resolve virtual method with Me */
    "CALLMETHOD",        /* call method with object on stack*/
    "CALLMYMETHOD",      /* call method belonging to Me */
    "NEW",               /* call to new */
    "NEWTEMP",           /* call to new", create on stack */
    "POWER",             /* power */
    "NEGATE",            /* negate value */
    "ADD",               /* addition */
    "SUB",               /* subtraction */
    "MUL",               /* multiplication */
    "DIV",               /* division */
    "IDIV",              /* integer division */
    "MOD",               /* modulus */
    "SHL",               /* bitwise left shift */
    "SHR",               /* bitwise right shift */
    "INV",               /* inverse */
    "CONCAT",            /* string concatenation */
    "OR_BITS",           /* bitwise or */
    "AND_BITS",          /* bitwise and */
    "ADD_SET ",          /* increment lval */
    "SUB_SET ",          /* decrement lval */
    "MUL_SET ",          /* multiply lval */
    "DIV_SET ",          /* divide lval */
    "IDIV_SET ",         /* integer divide lval */
    "MOD_SET ",          /* mod lval */
    "CONCAT_SET ",       /* concat lval */
    "EQ",                /* equality */
    "NE",                /* inequality */
    "LT",                /* less than */
    "LE",                /* less or equal than */
    "GT",                /* greater than */
    "GE",                /* greater or equal than */
    "NOT",               /* logical not */
    "DUP",               /* duplicate stack value */
    "AND",               /* logical and */
    "OR",                /* logical or */
    "XOR",               /* logical exclusive or */
    "CASERANGE",         /* range of case values */
    "CASE",              /* case test */
    "IN",                /* element is in array */
    "CREATEARRAY",       /* create an indexed array */
    "INITARRAY",         /* create an array with default values */
    "ERASEARRAY",        /* reset array back to default values */
    "CREATETABLE",       /* create a table */
    "SETLIST",           /* copy items from stack into table */
    "SETMAP",            /* map keys and values into table */
    "CREATELIST",        /* create a list */
    "GETSLICE",          /* return a slice from a list */
    "SETSLICE",          /* set a slice in a list */
    "FREE",               /* set variable to undefined */
    "VARIABLE",          /* return pointer to variable */
    "INDEX",             /* return pointer to value at index position */
    "PROP",              /* return pointer to property by index */
    "PROPBYNAME",        /* return pointer to property by name */
    "ME",                /* return pointer to current object */
    "GET",               /* put value of pointer onto stack */
    "SET",               /* store value on stack into pointer */
    "LVAL",              /* put pointer on stack */
    "SETTYPE"            /* set datatype for variable */
};

wVariant *wVmGetVariable( int index );
char *wVmVariableName( wSymbol *s, int index );
void wVmTypeCast( wVariant *variant );
void wVmTrace( wSymbol *sRoutine, int *pcode, int pc );
void wVmExecute( wSymbol *sRoutine );
void wVmDecompile( wSymbol *sRoutine );
int wVmDecompileOp( wSymbol *sRoutine, int *pcode, int pc );
void wVmDecompileAll( void );
void wVmShowOp( int opcode, int args, int arg1, int arg2, int arg3 );