request switch statement with common block

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


On Monday, 5 August 2013 at 04:07:55 UTC, Andre Artus wrote:
>
>>> 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.

I should point out that 'common_entry' and 'common_exit' are not 
really cases, but labels as they are not explicitly tied to the 
input expression.


More information about the Digitalmars-d mailing list