[Nickle]Twixt and exceptions

Keith Packard keithp@keithp.com
Tue, 20 Feb 2001 20:22:22 -0800


Two of the unfinished pieces in nickle are exception handling and "critical 
sections" -- pieces of code executed on the way out of a stack context 
during exeception handling.

* critical sections

A big problem Bart and I have seen with other languages is that the 
enter/leave portions of "critical sections" is assymetrical, we usually 
have:

	lock_mutex ()
	try {

		... lots of code here ...

	} finally {
		unlock_mutex ();
	}

or some such; this is unpleasing to the eye; the lock and unlock are
separated both by a large distance and are actually at different 
indentation levels.

Instead, Bart came up with the following syntax:

	twixt (<enter-expr>; <leave-expr>) <statement>

After <enter-expr> is executed, <leave-expr> is guaranteed to be executed.

So, you would do:

	twixt (mutex.acquire (m); mutex.release (m)) 
	{
		stuff with m locked
	}

Questions: how should this work with non-blocking syncronization 
primitives (mutex.tryAcquire, semahpore.test)?

Suggestion: initial statement is boolean, entry to twixt is denied if the 
first statement evaluates to False.

	twixt (mutex.tryAcquire (m); mutex.release (m))
	{
		stuff with m locked
	}

Problem: assymetry returns, need to capture tryAcquire result to learn if
'stuff' was executed.

Alternative: force program to handle this case:

	twixt (got = mutex.tryAcquire (m); got ? mutex.release (m) : 0)
	{
		if (got) {
			stuff with m locked;
		}
	}

or
	if (mutex.tryAcquire(m) twixt (; mutex.release (m)) 
	{
		stuff with m locked;
	}


Problem: Extra scope, or assymetrical usage.

Suggestions are welcome; I'm leaning towards the predicated twixt form.

* Exceptions.

Here's the current plan, it's not implemented but probably will be soon.

Exceptions are symbols declared with function-like syntax that can
be dynamically bound to a particular lamda.  Uncaught exceptions terminate 
the thread with an error.  An example would be helpful here:

	exception missing_q (string line);

	...

	s = "foobar";
	try {
		if (strings.index (s, "q") < 0)
			throw missing_q (s);
	} catch missing_q (string line) {
		printf ("Hey, bozo, no 'q' found in %s\n", line);
	}

Question: the 'catch' and 'throw' keywords are completely gratuitous 
syntactic sugar.  Can I get rid of them?  Or would the alternative be too 
confusing?

Would you prefer this syntax instead:

	{
		catch missing_q (string line) 
		{
			printf ("Hey, bozo, no 'q' found in %s\n", line);
		}

		if (strings.index (s, "q") < 0)
			throw missing_q (s);

	}

One I'm not fond of:

	catch missing_q (string line)
	{
		printf ("Hey, bozo, no 'q' found in %s\n", line);
	}
	{
		if (strings.index (s, "q") < 0)
			throw missing_q (s);
	}

This last form would require the 'catch' keyword to keep it parsable.

Complaints? Comments?

-keith