It seems that exception handlers get tied to 
subroutines when they're created, not when 
they're actually used. For example:

    ## this works:
    try:
        f = make_function()
        f.die() # raise some error
    except:
        pass

  
    ## this does not work:
    f = make_function()
    try:
       f.die() # raise some error
    except:
       pass


This is a problem in general, but especially for me
because in python, a generator returns an object, 
and you call that object's next() over and over 
until you get a StopIteration. Unfortunately, I
can't *trap* that StopIteration in a "try" block 
unless I create the generator inside that same block.

Following is a detailed test case in imc that 
illustrates the problem.

Sincerely,
 
Michal J Wallace
Sabren Enterprises, Inc.
-------------------------------------
contact: [EMAIL PROTECTED]
hosting: http://www.cornerhost.com/
my site: http://www.withoutane.com/
--------------------------------------

## generator_try_bug.imc

## this exposes a bug in parrot exception handling
## a function returns a function and that function
## throws an error. The error is not caught.

.sub __main__
    new_pad 0

    # count() returns a generator
    .local object count
    newsub count, .Closure, _count

    # here's where we'll store it
    .local object generator


# if "try:" is around the CREATION of the generator, 
# everything works fine. but we don't want that, so
# this is commented out.
#
#    .local Sub handler
#    newsub handler, .Exception_Handler, catch0
#    set_eh handler


    # call count and get the generator
    .local Sub retlabel0
    newsub retlabel0, .Continuation, ret0
    .pcc_begin non_prototyped
    .pcc_call count, retlabel0
ret0:
    .result generator
    .pcc_end


    ## HERE IS where we want the try block to start ####
    .local Sub handler
    newsub handler, .Exception_Handler, catch0
    set_eh handler


    # now call the generator, which throws 'StopIteration'
    .local Sub retlabel1
    newsub retlabel1, .Continuation, ret1
    .pcc_begin non_prototyped
    .pcc_call generator, retlabel1
ret1:
    .result $P3
    .pcc_end

    # end the "try" block (we never get here)
    clear_eh
    goto endtry0
catch0:
    print "caught it!"
endtry0:
    end
.end

# here is count(), which returns the generator
.pcc_sub _count non_prototyped
   .local object gen_fun
   .local object gen_obj
   newsub gen_fun, .Coroutine, _count_g
   .pcc_begin_return
   .return gen_fun
   .pcc_end_return
.end

# here is the generator itself
# all it does is throw StopIteration
.pcc_sub _count_g non_prototyped
    .local object ex0
    .local object msg0
    ex0 = new Exception
    msg0 = new PerlString
    msg0 = 'StopIteration'
    ex0['_message'] = msg0
    throw ex0
.end

## end of test case ###############################


Reply via email to