No more fall through in case statement?

BC notmi_emayl_adreznot at hotmail.com.remove.not
Fri Jan 4 09:09:21 PST 2008


On Thu, 03 Jan 2008 10:30:09 -0000, davidl <davidl at 126.com> wrote:

> http://pragmatic.oreilly.com/pub/a/oreilly/dotnet/news/programmingCsharp_0801.html
>
> I think I love the trap no.9
>


i had a go at rolling my own, here it is if anyone's interested:

//public domain
import std.stdio;
import std.variant;
import std.traits;

struct SwitchFrame
{
    Variant     val;
    bool        active;
    bool        _break;
    static SwitchFrame opCall(Variant val, bool active, bool _break)
    {
       SwitchFrame result;
       result.val    = val;
       result.active = active;
       result._break = _break;
       return result;
    }
}

SwitchFrame[] switchStack;

void _continue()  //execute next case after this one
{
    switchStack[$ - 1].active = true;
    switchStack[$ - 1]._break = false;
}

void _rematch()   //execute the next case that matches
{
    switchStack[$ - 1].active = false;
    switchStack[$ - 1]._break = false;
}

void _break()     //don't execute any more cases
{
    switchStack[$ - 1].active = false;
    switchStack[$ - 1]._break = true;
}


struct _range(T)
{
    T min;
    T max;
}

_range!(T) range(T)(T min, T max)
{
    _range!(T) result;
    result.min = min;
    result.max = max;
    return result;
}

struct rangedg(T)
{
    T min;
    T max;
    bool func(T val)
    {
       return min <= val && val <= max;
    }
}

void myswitch(T, U)(T switchVal, U block)
{
    Variant v = switchVal;
    switchStack ~= SwitchFrame(v, false, false);
    block();
    switchStack.length = switchStack.length - 1;
}

void mycase(T...)(T args)
{
    SwitchFrame* frame = &switchStack[$ - 1];
    if (frame._break) return;
    if (!frame.active)
    {
       foreach (i, arg; args[0 .. $-1])
       {
          if (typeid(T[i]) == frame.val.type && arg ==  
frame.val.get!(T[i])) goto success;

          static if (is (typeof(*arg) U == function))
          {
             //writefln("function");
             if (arg(frame.val.get!(U))) goto success;
          }
          static if (is (T[i] U == delegate))
          {
             //writefln("delegate");
             if (arg(frame.val.get!(ParameterTypeTuple!(U)))) goto success;
          }
          static if (is (T[i] U == _range!(V), V))
          {
             V switchVal1 = frame.val.get!(V);
             if (arg.min <= switchVal1 && switchVal1 <= arg.max) goto  
success;
          }

       }
    }
    else
    {
success:
       _break();// <- change this to change the default action
       args[$-1]();
    }
}

bool always(int a)
{
    return true;
}

void main()
{
    myswitch(24,
    {
       mycase(10, 11, 12,                 { writefln("10, 11, 12");  
_continue; });
       mycase(24,                         { writefln("24"        );  
_rematch;  });
       mycase(range(3, 25),               { writefln("range"     );  
_rematch;  });
       mycase((int a) { return a > 40; }, { writefln(">40"       );  
_rematch;  });
       mycase(&always,                    { writefln("always"    );  
_rematch;  });
    });
    _range!(int) ra = {2,3};
}



More information about the Digitalmars-d mailing list