Sophie

Sophie

distrib > Mageia > 1 > i586 > by-pkgid > d92aa75c2d384ff9f513aed09a46f703 > files > 85

parrot-doc-3.1.0-2.mga1.i586.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Parrot  - Exceptions</title>
        <link rel="stylesheet" type="text/css"
            href="../../../../resources/parrot.css"
            media="all">
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    </head>
    <body>
        <div id="wrapper">
            <div id="header">

                <a href="http://www.parrot.org">
                <img border=0 src="../../../../resources/parrot_logo.png" id="logo" alt="parrot">
                </a>
            </div> <!-- "header" -->
            <div id="divider"></div>
            <div id="mainbody">
                <div id="breadcrumb">
                    <a href="../../../../html/index.html">Home</a> &raquo; Exceptions
                </div>

<h1><a name="Exceptions"
>Exceptions</a></h1>

<p><!--
	INDEX: exceptions
--> Exceptions provide a way of subverting the normal flow of control.
Their main use is error reporting and cleanup tasks,
but sometimes exceptions are just a funny way to jump from one code location to another one.
Parrot uses a robust exception mechanism and makes it available to PIR.</p>

<p>Exceptions are objects that hold essential information about an exceptional situation: the error message,
the severity and type of the error,
the location of the error,
and backtrace information about the chain of calls that led to the error.
Exception handlers are ordinary subroutines,
but user code never calls them directly from within user code.
Instead,
Parrot invokes an appropriate exception handler to catch a thrown exception.</p>

<h2><a name="Throwing_Exceptions"
>Throwing Exceptions</a></h2>

<p><!--
	INDEX: exceptions; throwing
--> The <code>throw</code><!--
	INDEX: throw opcode
--> opcode throws an exception object.
This example creates a new <code>Exception</code><!--
	INDEX: Exception PMC
--> object in <code>$P0</code> and throws it:</p>
<pre>  $P0 = new 'Exception'
  throw $P0
</pre>
<p>Setting the string value of an exception object sets its error message:</p>
<pre>  $P0 = new 'Exception'
  $P0 = "I really had my heart set on halibut."
  throw $P0
</pre>
<p>Other parts of Parrot throw their own exceptions.
The <code>die</code><!--
	INDEX: die opcode
--> opcode throws a fatal (that is,
uncatchable) exception.
Many opcodes throw exceptions to indicate error conditions.
The <code>/</code> operator (the <code>div</code> opcode),
for example,
throws an exception on attempted division by zero.</p>

<p>When no appropriate handlers are available to catch an exception,
Parrot treats it as a fatal error and exits,
printing the exception message followed by a backtrace showing the location of the thrown exception:</p>

<pre>  I really had my heart set on halibut.
  current instr.: &#39;main&#39; pc 6 (pet_store.pir:4)</pre>

<h2><a name="Catching_Exceptions"
>Catching Exceptions</a></h2>

<p><!--
	INDEX: exception handlers
--> <!--
	INDEX: exceptions; catching
--> Exception handlers catch exceptions, making it possible to recover from errors in a controlled way, instead of terminating the process entirely.</p>

<p>The <code>push_eh</code><!--
	INDEX: push_eh opcode
--> opcode creates an exception handler object and stores it in the list of currently active exception handlers. The body of the exception handler is a labeled section of code inside the same subroutine as the call to <code>push_eh</code>. The opcode takes one argument, the name of the label:</p>
<pre>  push_eh my_handler
    $P0 = new 'Exception'
    throw $P0

    say 'never printed'

  my_handler:
    say 'caught an exception'
</pre>
<p>This example creates an exception handler with a destination address of the <code>my_handler</code> label, then creates a new exception and throws it. At this point, Parrot checks to see if there are any appropriate exception handlers in the currently active list. It finds <code>my_handler</code> and runs it, printing &#34;caught an exception&#34;. The &#34;never printed&#34; line never runs, because the exceptional control flow skips right over it.</p>

<p>Because Parrot scans the list of active handlers from newest to oldest, you don&#39;t want to leave exception handlers lying around when you&#39;re done with them. The <code>pop_eh</code><!--
	INDEX: pop_eh opcode
--> opcode removes an exception handler from the list of currently active handlers:</p>
<pre>  push_eh my_handler
    $I0 = $I1 / $I2
    pop_eh

    say 'maybe printed'

    goto skip_handler

  my_handler:
    say 'caught an exception'
    pop_eh

  skip_handler:
</pre>
<p>This example creates an exception handler <code>my_handler</code> and then runs a division operation that will throw a &#34;division by zero&#34; exception if <code>$I2</code> is 0. When <code>$I2</code> is 0, <code>div</code> throws an exception. The exception handler catches it, prints &#34;caught an exception&#34;, and then clears itself with <code>pop_eh</code>. When <code>$I2</code> is a non&#45;zero value, there is no exception. The code clears the exception handler with <code>pop_eh</code>, then prints &#34;maybe printed&#34;. The <code>goto</code> skips over the code of the exception handler, as it&#39;s just a labeled unit of code within the subroutine.</p>

<p>The exception object provides access to various attributes of the exception for additional information about what kind of error it was, and what might have caused it. The directive <code>.get_results</code><!--
	INDEX: .get_results directive
--> retrieves the <code>Exception</code> object from inside the handler:</p>
<pre>  my_handler:
    .get_results($P0)
</pre>
<p>Not all handlers are able to handle all kinds of exceptions. If a handler determines that it&#39;s caught an exception it can&#39;t handle, it can <code>rethrow</code> the exception to the next handler in the list of active handlers:</p>
<pre>  my_handler:
    .get_results($P0)
    rethrow $P0
</pre>
<p>If none of the active handlers can handle the exception, the exception becomes a fatal error. Parrot will exit, just as if it could find no handlers.</p>

<p><!--
	INDEX: exceptions;resuming
--> <!--
	INDEX: resumable exceptions
--></p>

<p>An exception handler creates a return continuation with a snapshot of the current interpreter context. If the handler is successful, it can resume running at the instruction immediately after the one that threw the exception. This resume continuation is available from the <code>resume</code> attribute of the exception object. To resume after the exception handler is complete, call the resume handler like an ordinary subroutine:</p>
<pre>  my_handler:
    .get_results($P0)
    $P1 = $P0['resume']
    $P1()
</pre>
<h2><a name="Exception_PMC"
>Exception PMC</a></h2>

<p><!--
	INDEX: Exception PMC
--> <!--
	INDEX: Exception PMC;message
--> <code>Exception</code> objects contain several useful pieces of information about the exception. To set and retrieve the exception message, use the <code>message</code> key on the exception object:</p>
<pre>  $P0            = new 'Exception'
  $P0['message'] = "this is an error message for the exception"
</pre>
<p>... or set and retrieve the string value of the exception object directly:</p>
<pre>  $S0 = $P0
</pre>
<p><!--
	INDEX: Exception PMC;severity
--> <!--
	INDEX: Exception PMC;type
--> The severity and type of the exception are both integer values:</p>
<pre>  $P0['severity'] = 1
  $P0['type']     = 2
</pre>
<p><!--
	INDEX: Exception PMC;payload
--> The payload holds any user&#45;defined data attached to the exception object:</p>
<pre>  $P0['payload'] = $P2
</pre>
<p>The attributes of the exception are useful in the handler for making decisions about how and whether to handle an exception and report its results:</p>
<pre>  my_handler:
    .get_results($P2)
    $S0 = $P2['message']
    print 'caught exception: "'
    print $S0
    $I0 = $P2['type']
    print '", of type '
    say $I0
</pre>
<h2><a name="ExceptionHandler_PMC"
>ExceptionHandler PMC</a></h2>

<p><!--
	INDEX: ExceptionHandler PMC
--> Exception handlers are subroutine&#45;like PMC objects, derived from Parrot&#39;s <code>Continuation</code> type. When you use <code>push_eh</code> with a label to create an exception handler, Parrot creates the handler PMC for you. You can also create it directly by creating a new <code>ExceptionHandler</code> object, and setting its destination address to the label of the handler using the <code>set_addr</code> opcode<!--
	INDEX: set_addr opcode
-->:</p>
<pre>    $P0 = new 'ExceptionHandler'
    set_addr $P0, my_handler
    push_eh $P0
    # ...

  my_handler:
    # ...
</pre>
<p><!--
	INDEX: can_handle method
--> <code>ExceptionHandler</code> PMCs have several methods for setting or checking handler attributes. The <code>can_handle</code> method reports whether the handler is willing or able to handle a particular exception. It takes one argument, the exception object to test:</p>
<pre>  $I0 = $P0.'can_handle'($P1)
</pre>
<p><!--
	INDEX: min_severity method
--> <!--
	INDEX: max_severity method
--> The <code>min_severity</code> and <code>max_severity</code> methods set and retrieve the severity attributes of the handler, allowing it to refuse to handle any exceptions whose severity is too high or too low. Both take a single optional integer argument to set the severity; both return the current value of the attribute as a result:</p>
<pre>  $P0.'min_severity'(5)
  $I0 = $P0.'max_severity'()
</pre>
<p><!--
	INDEX: handle_types method
--> <!--
	INDEX: handle_types_except method
--> The <code>handle_types</code> and <code>handle_types_except</code> methods tell the exception handler what types of exceptions it should or shouldn&#39;t handle. Both take a list of integer types, which correspond to the <code>type</code> attribute set on an exception object:</p>
<pre>  $P0.'handle_types'(5, 78, 42)
</pre>
<p>The following example creates an exception handler that only handles exception types 1 and 2. Instead of having <code>push_eh</code> create the exception handler object, it creates a new <code>ExceptionHandler</code> object manually. It then calls <code>handle_types</code> to identify the exception types it will handle:</p>
<pre>  $P0 = new 'ExceptionHandler'
  set_addr $P0, my_handler
  $P0.'handle_types'(1, 2)
  push_eh $P0
</pre>
<p>This handler can only handle exception objects with a type of 1 or 2. Parrot will skip over this handler for all other exception types.</p>
<pre>  $P1         = new 'Exception'
  $P1['type'] = 2
  throw $P1                     # caught

  $P1         = new 'Exception'
  $P1['type'] = 3
  throw $P1                     # uncaught
</pre>
<h2><a name="Annotations"
>Annotations</a></h2>

<p><!--
	INDEX: bytecode annotations
--> Annotations are pieces of metadata code stored in a bytecode file. This is especially important when dealing with high&#45;level languages, where annotations contain information about the HLL&#39;s source code such as the current line number and file name.</p>

<p>Create an annotation with the <code>.annotate</code><!--
	INDEX: .annotate directive
--> directive. Annotations consist of a key/value pair, where the key is a string and the value is an integer, a number, or a string. Bytecode stores annotations as constants in the compiled bytecode. Consequently, you may not store PMCs.</p>
<pre>  .annotate 'file', 'mysource.lang'
  .annotate 'line', 42
  .annotate 'compiletime', 0.3456
</pre>
<p>Annotations exist, or are &#34;in force&#34; throughout the entire subroutine or until their redefinition. Creating a new annotation with the same name as an old one overwrites it with the new value. The <code>annotations</code><!--
	INDEX: annotations opcode
--> opcode retrieves the current hash of annotations:</p>
<pre>  .annotate 'line', 1
  $P0 = annotations # {'line' => 1}

  .annotate 'line', 2
  $P0 = annotations # {'line' => 2}
</pre>
<p>To retrieve a single annotation by name, use the name with <code>annotations</code>:</p>
<pre>  $P0 = annotations 'line'
</pre>
<p>Exception objects contain information about the annotations that were in force when the exception was thrown. Retrieve them with the <code>annotations</code><!--
	INDEX: annotations method
--> method on the exception PMC object:</p>
<pre>  $I0 = $P0.'annotations'('line')  # only the 'line' annotation
  $P1 = $P0.'annotations'()        # hash of all annotations
</pre>
<p>Exceptions can also include a backtrace<!--
	INDEX: backtrace method
--> to display the program flow to the point of the throw:</p>
<pre>  $P1 = $P0.'backtrace'()
</pre>
<p>The backtrace PMC is an array of hashes. Each element in the array corresponds to a function in the current call chain. Each hash has two elements: <code>annotation</code> (the hash of annotations in effect at that point) and <code>sub</code> (the Sub PMC of that function).</p>
            </div> <!-- "mainbody" -->
            <div id="divider"></div>
            <div id="footer">
	        Copyright &copy; 2002-2011, Parrot Foundation.
            </div>
        </div> <!-- "wrapper" -->
    </body>
</html>