[nem-en] Semantics of 'expose' macro construct when an exception is thrown.

Gerard Murphy g.j.murphy at sageserpent.com
Wed Dec 7 00:22:29 CET 2005


Hello,

I was investigating why the following class doesn't pass a unit test, when I
noticed that exceptions thrown in an 'expose' block are not propagated out
of the block.

This seems surprising. I would indeed expect the class invariant to be
checked on the object specified in the 'expose' statement, regardless of
whether the block completes normally or throws an exception: but in the
latter case I would also expect the exception to be rethrown and propagated
after checking the invariant (assuming the invariant wasn't violated).

Here's the code.

namespace SageSerpent.Core.TestSupport
{
    using System;
    using System.Collections.ObjectModel;
    using Nemerle.Assertions;
    using Nemerle.Imperative;

    public
    class TestCaseSet: KeyedCollection[Object, Object]
    invariant AllTestCaseReferencesAreNonNull()
    {
        protected override
        GetKeyForItem(item: Object): Object
        {
            item
        }
        
        protected override
        InsertItem(index: Int32,
                   value: Object): void
        requires value != null
        {
            System.Console.WriteLine("In InsertItem before expose block.");
            expose(this)
            {
                base.InsertItem(index, value);
                    throw System.Exception("Bogus!")   // ***** AN EXCEPTION
IS THROWN HERE ****
            }
            System.Console.WriteLine("In InsertItem after expose block.");
        }
        
        protected override
        SetItem(index: Int32,
                value: Object): void
        requires value != null
        {
            System.Console.WriteLine("In SetItem before expose block.");
            expose(this)
            {
                base.SetItem(index, value)
            }
            System.Console.WriteLine("In SetItem after expose block.");
        }
        
        private
        AllTestCaseReferencesAreNonNull(): bool
        {        
            foreach (testCaseReference in this)
            {
                when (testCaseReference == null) return false
            }
            
            true
        }
    }
}

During execution of the unit test, the TestCaseSet.InsertItem() method is
called repeatedly. However, observing the console output indicates that the
statement following the 'expose' block is executed; presumably the exception
is being 'eaten' by the macro expansion of the 'expose' block.

As far as I can see, the invariant is not being violated during execution of
the unit test: so I would expect to see the bogus exception being propagated
(as opposed to either a Nemerle.Assertion exception being propagated or
execution continuing normally after the 'expose' block).


I presume this is a bug - but I would welcome comments if this was the
intent of the language designers.

I'm completely in the dark as to what Spec# would do in this situation, by
the way. I'll go and have a look. :-)

Many thanks,

Gerard

Gerard Murphy www.sageserpent.com






More information about the devel-en mailing list