Moto is an embedded language. That means that any text file, HTML page, or XML document is
by default a legal moto file. The contents of such a file would pass through the moto
interpreter and print out unmodified. Moto actually does something when, in the process
of parsing a file, it runs into a moto construct. These are special directives that begin with
the character $.
To comment out a block of text you want moto to ignore,
surround that text by $* and *$ . Unlike HTML comments, commented text
will not appear in the output of either the moto compiler or interpreter.
To use the dollar sign $ in your moto file without what follows being interpreted as
a macro or malformed moto construct you must escape it with a backslash
Note that backslashes not followed by a dollar sign are treated as literal and need not
be escaped. Thus the code used to produce the previous example was
Moto supports the use of local variables. Prior to use, a local variable must first
be declared.
$declare(variable type variable name)
| |
The initial value of a variable may also be set at declaration time.
$declare(variable type variable name = initial value )
| |
You may not declare a variable with the same name more than once in a page. That means that you
may not declare a variable with the same name in a macro that is used on the page or in a file that
is included in the page. Unlike C, moto does not require all declarations to be at the beginning
of a page , but it's still good practice.
The storage for local variables is
lost after executing a page. Thus these variables are said to have
a page lifetime. Variables declared within a loop or conditional block
may not be used after (outside of) that conditional block or loop.
Such variable have a scope lifetime.
Variables may be of basic types or object types. Basic types include:
double |
may be assigned any byte, char, int, float, long or double value |
float |
may be assigned any byte, char, int, float, long or double value |
long |
may be assigned any byte, char, int, float, long or double value.
Moto longs are 64 bits in length thus the maximum and minimum values are 9223372036854775807 and
-9223372036854775808 respectively |
int |
may be assigned any byte, char, int, float, long or double value.
Moto ints are 32 bits thus the maximum and minimum values are 2147483647 and -2147483648
respectively |
byte |
may be assigned any byte, char, int, float, long or double value. Bytes are signed
ints 8 bits long thus the maximum and minimum values are 127 and -128 respectively |
boolean |
may be assigned true or false or the value of a relational
expression |
char |
may be assigned any character in sigle quotes '' including standard C
escape characters such as '\n' '\r' or '\t'. It may also be assigned a
value in hex or octal representation e.g. '\x41' == '\101' == 'A' as well
as any numeric value |
| |
The char, byte, double, float, long, and int types collectively make up the supported basic numerical
types. They can be combined to form expressions via the following operations:
A + B |
adds A and B together or converts one variable to a String and concatenates
it to the other if the other is already a String. |
A - B |
subtracts B from A |
A * B |
multiplies A and B |
A / B |
divides A by B. When B is 0 a division by zero exception will be thrown |
A % B |
provides A mod B (only works if A and B are longs or ints |
| |
When numeric variables of different types appear in an expression, expanding casts are used
so that the most precise answer is maintained (i.e. a long plus an int yields a long, an int
divided by a float yields a float etc...). Only numeric variables and chars are implicitly cast,
booleans are not. The set of boolean operators will be described in
the section on conditionals.
The integral types byte, char, int, and long may also be acted on by bit manipulation
operators
A | B |
Bitwise OR will turn any bit to 1 in the expression result that was 1 in
either A or B. The corresponding bit in the result will be 0 otherwise |
A & B |
Bitwise AND will turn any bit to 1 in the expression result that was 1 in
both A and B. The corresponding bit in the result will be 0 otherwise |
A ^ B |
Bitwise XOR will turn any bit to 1 in the expression result that was 1 in
either A and B but not both. The corresponding bit in the result will be
0 otherwise |
~A |
Bitwise NOT will turn any bit to 1 in the expression result that was 0 in
A. Otherwise the corresponding bit in the result will be 0 |
A << B |
Left shift shifts the bits of A B bits to the left and fills the rightmost B
bits with 0. The A << 2 would multiply A by 4 |
A >> B |
Right shift shifts the bits of A B bits to the right and fills the leftmost B
bits with 0. The A >> 2 would divide A by 4 |
| |
Object types are anything else. As a rule, all basic types begin with a lower case
letter all object types begin with an uppercase letter. There is language level support
for three types of objects :
String |
may be assigned a character string between double quotes "" |
Regex |
may be assigned a regular expression between forward slashes /.../ |
Object |
may be assigned an object of any typed |
| |
The plus operator may also be used to append Strings together. When basic types are added to
strings they are automatically converted to strings first.
Other types of objects become available via the $use keyword.
When creating a new object use the new keyword and then call that objects constructor
$declare(Hashtable htab = new Hashtable())
| |
Objects you create may need to be deleted later depending upon which memory manager you are using.
This is done using the delete keyword.
All object types may also be assigned the special value null
$declare(Hashtable htab = null)
| |
The capital 'O' Object type is special in that it may be assigned a value of any other
object type.
$declare(Object htab = new Hashtable())
| |
This is important for objects that are designed to store other objects such
as Vectors or Stacks. There are no methods that can be called on a pure Object type.
Rather, before an Object can be used it must be cast to the appropriate type.
$declare(Object obj = new Hashtable())
$declare(Hashtable htab = <Hashtable>obj)
| |
To call a function or assign a value to a previously declared variable
use the $do construct. The following operators assign values to variables:
A = B |
The variable A is assigned the value of expression B |
A += B |
If A and B are both numeric types the variable A is incremented by the
result of expression B. If A is a String then the result of evaluating
expression B is converted to a String and appended to A. |
A -= B |
The variable A is decremented by the result of expression B (note that A
and B must both be numeric types) |
A *= B |
The variable A is multiplied by the result of expression B (note that A
and B must both be numeric types) |
A /= B |
The variable A is divided by the result of expression B (note that A
and B must both be numeric types) |
A++ |
The integer, long, byte, or char variable A is incremented by 1 |
A-- |
The integer, long, byte, or char variable A is decremented by 1 |
++A |
The integer, long, byte, or char variable A is incremented by 1 |
--A |
The integer, long, byte, or char variable A is decremented by 1 |
| |
There are times when you might want to do 'more than one thing at once' . For this
you can use the comma operator. The comma operator allows you to execute multiple expressions
one after another as a single expression. The result and type of the compound
expression is determined solely by the last expression executed:
Read 'dollar print', this construct is used to output an expression or result
of a function call. All non String expression results are converted to Strings prior
to being output.
$if(condition)
code to be executed if condition is true
$elseif(some other condition)
code to be executed if other condition is true
$else
code to be executed if previous conditions are false
$endif
| |
As in other languages, the basic conditional statement consists of an opening if
construct, followed by any number of else if conditions, followed by an optional
else construct, then a mandatory endif. Unlike languages such as C however, conditions
in moto must be booleans. The following comparison operators return boolean
values:
A > B |
numeric variable A is greater than numeric variable B |
A >= B |
numeric variable A is greater than or equal to numeric
variable B |
A < B |
numeric variable A is less than numeric variable B |
A <= B |
numeric variable A is less than or equal to numeric variable B |
A == B |
the value of basic variable A equals the value of basic variable B OR
the reference variable A refers to the same object as the reference
variable B |
A != B |
the value of basic variable A does not equal the value of basic variable B
OR
the reference variable A does not refer to the same object as the reference
variable B |
A eq B |
the String variable A has the same content as the String variable B |
A ne B |
the String variable A does not have the same content as the String variable B |
A lt B |
The String A would come before B when sorted alphabetically |
A gt B |
The String A would come after B when sorted alphabetically |
A lte B |
The String A would come before B when sorted alphabetically OR A has the same
content as B |
A gte B |
The String A would come after B when sorted alphabetically OR A has the same
content as B |
A =~ B |
the regular expression B matches a substring of the String A |
A !~ B |
the regular expression B does not match any substring of the String A |
| |
In addition the following operations can be used on boolean expressions to
create more complex boolean typed expressions.
A && B |
Expression is true if and only if subexpressions A and B are true |
A || B |
Expression is true if either subexpression A or B is true |
!A |
Expression is true if subexpression A is false |
| |
Like C, short circuit evaluation is used when evaluating compound boolean operators.
$switch(expression)
code for default case
$case(value 1)
code for case 1
$case(value 2)
code for case 2
$case(value 3)
code for case 3
$endswitch
| |
You can switch on any basic type expression as well as Strings.
Unlike C, execution does not 'fall through' cases, rather the
next case ends the previous. Another important difference from C
is the lack of an
explicitly specified default case. In moto, the default behavior
is to execute whatever code is specified between the switch statement
and the first case. The following example illustrates how switch
statements are used to display the examples used in this document.
$use("codex.util")
$declare(String example = getFile("/content/moto/parse_example.moto"))
$declare(StringBuffer displayExample = new StringBuffer())
$declare(int i=0)
$declare(char lastchar = '\0')
$for(i=0;i<example.length();i++)
$switch(example.charAt(i))
$* default *$
$do(displayExample.append(example.charAt(i)))
$case('<')
$do(displayExample.append("<"))
$case('>')
$do(displayExample.append(">"))
$case('&')
$do(displayExample.append("&"))
$case('\n')
$do(displayExample.append("<br>\n"))
$case('\t')
$do(displayExample.append(" "))
$case(' ')
$if(lastchar == ' ')
$do(displayExample.append(" "))
$else
$do(displayExample.append(' '))
$endif
$endswitch
$do(lastchar = example.charAt(i))
$endfor
$(displayExample.toString())
| |
Not a construct, but an operator, the ternary operator may be used to within an
expression to return one of two same typed outputs. In the example above the expression
returns the subexpression A if the specified condition evaluates true, B otherwise.
For loops in moto work very similar to for loops in C, C++, or Java.
$for(initialization;condition;increment)
code to be repeated
$endfor
| |
The initialization expression is executed prior to looping. It is
used to set up the initial conditions for the loop itself. The condition
expression is tested on each iteration of the loop (including the first iteration
immediately after initialization). Unline C or C++ the condition expression must be
a boolean expression. The increment expression is executed after each iteration of the
loop. It is immediately after the increment expression is executed that the condtion
is tested again. When the condition expression becomes false the loop terminates. For instance to
execute a loop ten times you might write
$for(i=0;i<10;i++)
code to be repeated
$endfor
| |
This assumes the variable 'i' was declared prior to being used in the loop. Like Java
a variable may be declared within the initialization expression.
$for(int i=0;i<10;i++)
code to be repeated
$endfor
| |
$while(condition)
code to be repeated
$endwhile
| |
Executes the code to be repeated while the boolean condition remains true.
$while(condition)
code to be repeated
$if(some other condition)
$break
$endif
more code to be repeated
$endwhile
| |
Breaks out of the last open loops (continues after the next $endfor or
$endwhile)
$while(1st condition)
code to be repeated
$if(2nd condition)
$continue
$endif
code to be repeated only if 2nd condition is false
$endwhile
| |
Returns to the first line of the most recently opened loop (and increments
the counter in a for loop).
To define a function in moto use the $define construct. In it you must specify the return type
of the function (use the return type void if the function returns nothing). Follow the
return type with the name of the function and then the arguments the function will take in
parenthesis. The argument list should take the form type argument-name,type argument-name, ...
for as many arguments as you have. You can specify an empty argument list.
$define(return-type name(argument list))
...
$return(expression)
...
$enddef
| |
Function definition in moto must occur in the top scope. You cannot define a new function inside
a condition, iterative, or scoping block. You can however use functions before they are
defined within a moto page. Unlike C there is no need (and no way) to explicitly prototype functions
before using them.
To return a value from a function use the $return construct. The type of the expression returned must however
match the specified type of the function. $return must be inside a $define ... $enddef scope or else it is
a syntax error.
You can specify multiple functions with the same name as long as they take a different number of arguments, or
different argument types, or the same argument types in a different order.
Functions in moto do not normally have access to variables declared outside of them. Only variables declared as
global before the function definition can be used within a moto function. Otherwise only arguments to that function
and variables declared within the body of the function can be used. To declare a variable as global use the global
type qualifier
$declare(global int statements=0)
| |
Like functions, globals can only be declared at the top level and are not allowed in nested scopes.
A Class is used to aggregate data of different types into a new type and associate with that
new type
methods which act on the aggregated data. Once a class is defined,
variables can be declared of type Class Name. These variables can then be
assigned instances of the Class also called Objects.
Class definition must occur in the top scope. You cannot define a new Class inside
a condition, iterative, function definition, or scoping block.
A Class is defined with the following syntax:
$class(<class name>)
<member variable declarations>
<method definitions>
$endclass
| |
Variable declarations inside a Class definition become member variables of that Class.
Functions defined within Class Definitions become methods of the Class. Methods with the
same name as the Class are called constructors. Constructors must not specify a return type.
Assignments to
member variables at declaration time become part of the Class's Implicit Constructor.
These assignments will take place whenever an instance of the Class is created. Class instances
are created by using the 'new' keyword.
$declare(<class name> <var name> = new <class name>(<constructor arguments>))
| |
Three distinct operations occur when an Object is instantiated:
- Storage is allocated for the Object
- The implicit constructor is called assigning initial values to the Object's member variables
- The explicit constructor (the constructor whose arguments match those passed in) is called
to do further initialization of member variables.
If no no-arg constructor is explicitly defined then calling
$declare(<class name> <var name> = new <class name>())
| |
will still succeed and the implicit constructor alone will be called. If arguments are passed
to the constructor then and explicit constructor with matching arguments must be defined
Member variables are retrieved using the dereference operator '.'.
$do( <variable name>.<member variable name> = <value>)
| |
Class member variables are used within method definitions by using the member variable's name.
However, member variables may be shadowed within a method if the method takes an argument or
declares a local variable of the same name. Even this case member variables can still be accessed
by making use of the special variable 'this'. The value of the variable 'this' is always
the instance of the class the method is being called on. Thus within a method definition the expression
'this.<member variable name>
will return the specified member variable. The variable 'this' may not be shadowed or assigned to
or re-declared as a local variable or argument.
Methods are called on Objects by using the dereference operator '.'.
$do( <variable name>.<method name>(<method arguments>))
| |
The $use construct provides access to extension libraries. These libraries, located on disk
under the mx directory of your moto installation, provide definitions for a number of
objects and functions. The extensions included with the moto distribution are
moto | This extension library contains the definition for String objects
as well as object wrappers for the fundamental types (Boolean, Character, Double, Float,
Integer, and Long). This extension is used automatically by moto and does not need to
be explicitly used in a moto page. |
cstdlib | This extension library makes a number of functions from the
C standard libraries available to moto programmers |
codex.util | This extension library provides interfaces to the codex
library of utility objects. These objects include : Enumeration, FileIO, Hashset,
Hashtable, IntEnumeration, Inthashtable, IntSet, IntStack, ItoIHashtable, KMPString,
Stack, StringBuffer, Stringset, SymbolTable, Tokenizer and Vector. |
codex.http | This extension library provides objects for session and
state management in web applications, as well as basic function libraries for
interoperating with the Apache webserver. The interfaces included are: Context, Session
State, and HTTPRequest. |
codex.io | This extension library provides objects for interacting with
a Posix file system. Objects included are: PosixFileSystem.
|
codex.db.mysql | This extension library provides objects for interacting with
a MySQL database. Objects included are: MySQLConnection
and MySQLResultSet. |
codex.db.pgsql | This extension library provides objects for interacting with
a Postgres database . Objects included are: PGConnection and PGResultSet. |
| |
The $use construct can only be placed in the top level scope of a moto page and may not be placed
inside any conditional, iterative, or scoping block.
New extensions can be added by the creation of subdirectories under the mx directory. Objects
may be added to an extension via the creation of an interface (.i) file for that object.
In Moto, arrays are also considered a subclass of Object.
You cannot however instantiate an object of type "Array", rather you must declare
and instantiate an array based upon the sub-type it stores.
$declare(int foo[] = new int[5])
| |
The above example declares an int array 'foo' and then allocates the storage
for five ints with the new keyword
To get or set the value of of one of the indexes in the array you use the subscript operator
'[' ']'
$do(foo[1] = 3)
$(foo[1])
| |
All array indexes start at 0 so in the above example 0 through 4 would be valid indexes
in the array 'foo'. If foo[5] was accessed at runtime an ArrayBoundsException would be thrown.
Only integer
typed expressions can be used for array access, thus in moto only expresions of type int or
type long may be used.
If you know the contents of the array at declaration time you can specify it inline as follows.
$declare(int[] bar = {1,2,3})
| |
Note that the above example is really just shorthand for assigning the array 'bar' new int[3] and
then setting the individual elements of that array to 1,2, and 3 from first to last. The allocation
still occurs dynamically on the heap.
You can use similar syntax to construct instances of pre-defined arrays anywhere in your code.
This is done using the cast operator.
$(new String(<char []>{'h','e','l','l','o',' ','w','o','r','l','d'}))
| |
Moto also allows for the declaration and instantiation of multi-dimensionsal arrays.
$declare(char bar[][] = new char [3][2])
| |
The above example declares the variable bar to be a two dimensional array of characters,
then assigns to it a new two dimensional array for characters size 3 by 2. Multi-dimensionsal
arrays in Moto work the same way they do in Java. Instead of allocating one Object
of size dim 1 * dim 2 * dim 3 etc. multiple Objects are allocated so that the above new statement
actually creates the following 4 Objects:
This allows the flexibility of declaring arrays where the dimensions of nested arrays are
not equal (to represent adjacency lists for example)
$declare(char bar[][] = new char[3][])
$do(bar[0] = new char[3])
$do(bar[1] = new char[1])
$do(bar[2] = new char[2])
| |
Since arrays are objects, sub-arrays of multi-dimensional Array may even correspond to
the same Array
$declare(char bar[][] = new char[3][])
$do(bar[0] = bar[1] = bar[2] = new char[2])
| |
Arrays are passed to Moto functions by reference. Thus moto functions may alter the values
of array subscripts.
$define(void foo(int bar[]))
$do(bar[0] = 27)
$enddef
$declare(int maka[] = new int[3])
$do(foo(maka))
$(maka[0])
| |
Therefore the above example would output '27'.
The length of any array may be retrieved at runtime with the length() function thus
$declare(char bar[][] = new char[3][])
$(length(bar))
| |
would output '3' .
Arrays may be implicitly cast to Objects for the purposes of function calls. Moreover arrays of
subclasses of Objects and multidimensional arrays may be implicitly cast / assigned to
object arrays (Object[]).
Character and byte arrays have special handling in the moto language. Both may be output using the print
$() construct. Both may be appended to Strings with the string addition operators. Both may be converted
to Strings directly using the String constructor or the str() function.
Sometimes things go wrong at runtime. For instance a program might request input from a user that
is used to subscript an array at a certain index, but the index is outside of array bounds. Or
perhaps the array was never initialized and is null. Both of these errors may be checked for ahead
of time in the code, but others are not so easy to check for ahead of time. For instance when a program
performs a long database query and halfway through the connection to the database is severed. Or a
program needs to wrtie a file to disk but the disk is full, or write permissions haven't been
properly granted to the program. In these last two examples the condition that causes the error could either
not have been checked for ahead of time, or there are so many possible reasons the action
might fail that checking for all of them individually just isn't code efficient.
In all of these cases moto will throw an Exception . Throwing and exception is a lot like returning
from a function early. However when an exception is thrown, the active functions or methods on the moto
stack will keep returning until the Exception is caught or until there is no possible code left to catch
them at which point an Uncaught Exception error will be displayed.
What this really boils down to is that if you have a treacherous piece of code that may throw an Exception at
runtime, that you want to be able to deal with, you must wrap that code in a try-catch block. Take
for example the array bounds case from earlier.
$declare(char bar[] = new char[3])
$do(bar[4] = 'd')
| |
The above cade segment will surely fail since we are accessing an array index outside of declared bounds.
However, were we to write the following :
$declare(char bar[] = new char[3])
$try
$do(bar[4] = 'd')
$("I did a bad thing")
$catch(Exception e)
$("I caught an exception!")
$endtry
| |
The above code will not fail but instead will output 'I caught an exception!' . It will not
output 'I did a bad thing' because as soon as the exceptional condition occurred the program started
looking for a catch statement that would handle it.
From the syntax of of the $catch statement you may have already guessed that Exceptions are a type
of Object. The catch statement declares a local variable within the catch block that references the
exception so that important information may be gleaned from it and perhaps presented to the user. In
the previous example we declared the exception e to refer to the Exception that was caught. All exceptions
have at least the following methods :
Method |
Description |
Exception Exception() | Constructs a new Exception object |
Exception Exception(String message) | Constructs a new exception object with the
specified message. |
String toString() | Returns the type of the exception and any message included in the
exception as a String |
String getFile() | Returns the name of the file from which the Exception was thrown |
int getLine() | Returns the line number of the file where the Exception occurred |
String getStackTrace() | Returns a string representation of the call stack as it was when the Exception was thrown |
| |
Re-writing the previous example to use these methods we have:
$declare(char bar[] = new char[3])
$try
$do(bar[4] = 'd')
$("I did a bad thing")
$catch(Exception e)
$("I caught an exception!")
$(e.toString())
$(e.getFile()+":"+e.getLine())
$endtry
| |
This program would output :
ArrayBoundsException : Attempt to subscript array outside of declared bounds
myfile.moto:3
| |
Notice that the type of the Exception is ArrayBoundsException. Yet what we caught was just Exception.
This works because all Exceptions are sub-classes of Exception so simply catching an Exception will
catch all runtime exceptional conditions. If we had wanted too, than in the above catach we could have
caught ArrayBoundsException specifically. Only rarely do you want to catch all possible types of
Exceptions. Rather a program should catch only the Exceptions that the program can handle.
$declare(char bar[] = new char[3])
$declare(String foo = null)
$declare(boolean keepTrying = true)
$declare(int index = 4)
$while(keepTrying)
$try
$do(bar[index] = 'd')
$(foo.length())
$do(keepTrying = false)
$catch(ArrayBoundsException e)
$("I caught an ArrayBoundsException, better set index!")
$do(index=2)
$catch(NullPointerException e)
$("I caught a NullPointerException, better set foo!")
$do(foo="happy")
$endtry
$endwhile
| |
When either an ArrayBoundsException or a NullPointerException is thrown in the above example
the program takes the action neccessary to make sure that they are not thrown again. It keeps looping
until all the statements in the try block execute successfully. This program outputs :
I caught an ArrayBoundsException, better set index!
I caught a NullPointerException, better set foo!
5
| |
What the above program demonstrates is that a program can and should take different actions depending
on the exception that is thrown. It also makes use of the third type of built in moto exception.
While most Exceptions are thrown from extension function or method calls, Moto code may throw the
following types of Exception at runtime :
Exception |
The superclass for all other exceptions, when caught handles all other Exceptions |
NullPointerException |
Thrown whenever an null array is subscripted or a method is called on a null object or a
null object is dereferenced |
ArrayBoundsException |
Thrown whenever an array is subscripted outside its declared bounds. |
MathException |
Thrown whenever a numeric type is divided by zero. |
| |
Perhaps you have written some code that has it's own set of unique exceptional conditions and you
want to throw your own exceptions. This is accomplished by first constructing a new Exception, and
second throwing it with the $throw construct.
$throw(new Exception("You shouldn't have done that"))
| |
You may also throw any of the Exception subtypes loaded from different extensions. A common
exception you might throw is an IllegalArgumentException. It should be thrown when a function or
method gets passed an argument that it is not designed to work with.
$define(String getAreaCode(String phoneNumber))
$declare(Regex phoneRx = /[(]([0-9][0-9][0-9])[)][0-9][0-9][0-9][\-][0-9][0-9][0-9][0-9]/)
$if(phoneNumber == null)
$throw(new IllegalArgumentException("The phone number string provided may not be null"))
$endif
$declare(Match match = phoneRx.match(phoneNumber))
$if(match.subMatch(1) == null)
$throw(new IllegalArgumentException("The phone number provided is in an incorrect format"))
$endif
$(match.subMatch(1))
$enddef
| |
Often times it is important to have operations that are guaranteed to take place regardless of the success
or failure of the preceeding operations. A common example of this occurs when dealing with pools of
objects. The methodolgy for using an object pool is to grab an object out of it, call some methods on
that object, and when you're done, return the object to the pool. During the course of calling methods
on the object an exception may be thrown. Some types of exceptions you might want to catch, others you
might not. In all cases you want to make sure that the object gets returned to the pool. If it is not
your program will have a resource leak.
To specify code to execute regardless of the success or failure of the code you're trying to execute
you must use the $finally keyword.
$try
code we want to try to execute
$catch(FooException f)
code to be executed if a FooException got thrown
$catch(BarException b)
code to be executed if a BarException got thrown
$finally
code we want executed regardless of whether an exception occurred even if we caught it
$endtry
| |
A finally block gets executed no matter what. If the try block is inside of a function call
and the function returns from inside the try block or a catch block, the finally block will still get
executed. If the try block is inside a loop and the break or continue statement is used, the finally block
code will still get executed. If an exception gets thrown but not caught and passes through three different
try-catch-finally blocks, the finally blocks of all three will be executed.
The semantics of Moto Exception handling are the same as Exception handling in Java. An exception,
once thrown will jump to the end of the most recently opened try block. Its type will be compared
with the types of exceptions caught in any catch block opened after that try block. If its type
matches than that exception is said to have been handled and the code for that catch block is executed.
Regardless of whether the exception was handled or not, or whether or not there was an exception, the
finally block code, if present, is then executed. If there was an exception thrown and it was not handled
then once any finally block code has been executed the exception is re-thrown.
If an exception is thrown from within a catch block, and it is not handled (by way of a nested try-catch block)
than that exception overrides the current exception. However exceptions thrown from within catch blocks
are not compared with the types of Exceptions handleable by the current try-catch block. Rather the finally
code is executed and the new exception is re-thrown.
If an exception is thrown from within a finally block, and it is not handled by way of a nested try-catch block,
than that exception overrides the current exception if there is one and it is immediately re-thrown. If an exception
is generated from within a finally block but is handled by that same finally block (by way of a nested try catch) but
another exception had already been generated and not handled before entering the finally block, than after finally
block execution the original exception is re-thrown.
If a break, return, or continue is generated from within a try block than the finally block is executed and
the break, return, or continue action takes place. If however within the finally block there is a different sort
of jump statement such as another break, return, or continue, or even an exception getting thrown, than that action overrides
the action specified within the try block. If a break, return, or continue action is generated from within a catch
block than it can still be overridden by an action in the finally block.
Copyright © 2000 - 2003 David Hakim