request switch statement with common block

Andre Artus andre.artus at gmail.com
Sun Aug 4 21:07:50 PDT 2013


>> Andre Artus:
>> int number;
>> string message;
>> switch (number)
>> {
>> 	default: // valid: ends with 'throw'
>> 		throw new Exception("unknown number");
>> 	case 3:
>> 		message ~= "three "; break;
>> 	case 4:
>> 		message ~= "four "; continue;
>> 	case 5:
>> 		message ~= "five "; goto case;
>> 	case 6:
>> 		message ~= "six "; break;
>> 	case 1:
>> 	case 2:
>> 		message = "one or two";
>> }
>>
>> With the inclusion of 'default' the condition covers the whole 
>> range of 'int'. The programmer may only want the pre  and post 
>> code to be executed for every other case (1..6).

> MattCoder:
> Like I said, it would be nice if we could extend some D 
> features without change the compiler source, maybe like macros 
> in LISP.

It may not always be the case, but in my experience this often 
leads to write-only code.
I'm pretty new to D, so I'm not quite up to speed with the 
metaprogramming abilities, but I'm under the impression that this 
is what mixin's are for.

> MattCoder:
> The switch statement should have an event handler like: 
> onBeforeMatch or onAfterMatch to handle this.
>
> But for what I saw on this thread, this is only possible 
> changing the compiler source. :/
>
> Matheus.

In order to produce the most sane (in my opinion) construct the 
code cannot be rewritten as JS suggested:

> JS:
>
> if (cond) { <common_body1> }
> switch (cond)
> {
>     case <symbol> : <case body> [break or return or fallthrough]
>     ...
>     <default> : <default_body>  [break or return or fallthrough]
> }
> if (cond) { <common_body2> }
> if (!cond) { <else_body> }

As I mentioned before `switch` takes an expression that evaluates 
to integral or char[], the condition is completed in the `case`. 
The condition leading to the 'common' entry and exit code must 
replicate that of the complete switch statement. This begs the 
question about how to handle `default`. It would be difficult to 
correctly reason about the code without additional information.

The only suggestion that leads to sane results in all (maybe?) 
cases is that made by Ary Borenszweig.

> Ary Borenszweig:
>
> switch(cond) {
>   case A:
>     common_code();
>     // something
>   case B:
>     common_code();
>     // something else
> }

I would think that the common code could be factored into a 
function taking a void delegate (analogous to C# Action<T> 
delegate) then passing the case specific code as a lambda. This 
is something I have done in C#, but not yet in D.

In C# you would something like this:

private void UseAGoodNameDescribingCommonCode(Action action)
{
     // Entry code
     action();
     // Exit code
}

switch(expression) {
   case A:
	UseAGoodNameDescribingCommonCode(() => {
	    // something	
	});
	break;
   case B:
	UseAGoodNameDescribingCommonCode(() => {
	    // something	
	});
	break;
   default:
   	// Something else
}

It's very clear where it's being applied, and where it is not.

If the compiler was rewriting the following:

switch(expression) {
	common_entry:	// should not be order specific i.e. overloading 
'common'
		// entry code
		break;
	common_exit:
		// exit code
		break;
	case A:
		// something
		break;
	case B:
		// something else
		break;
	default:
		// default something
}

It could produce something like this:


switch(expression) {
	common_entry: // should not be order specific i.e. overloading 
'common'
		// entry code
		goto pop_label();
	common_exit:
		// exit code
		break;
	case A:
		// could set var or register used push/pop for clarity of intent
		push_label(A_prime);
		goto case common_entry;
	label A_prime:
		// something
		goto case common_exit;
		// break not needed here;
	case B:
		// rinse & repeat
	label B_prime:
		// rinse & repeat
	default:
		// default something
}
What to do with default needs to be disambiguated.


More information about the Digitalmars-d mailing list