CommandHelper

CommandHelper

46.5k Downloads

die() or return() in switch() with braces

LadyCailinBot opened this issue ยท 5 comments

commented

CMDHELPER-2985 - Reported by PseudoKnight

There's some odd behavior when die() or return() is in a switch when using brace syntax. (build 2784) Example:

switch('b') {
  case 'a':
    die('failure');
  case 'b':
    msg('success');
}
# No output

Even stranger is when you change this:

switch('b') {
  case 'a':
    if(true) {
      die('failure');
    }
  case 'b':
    msg('success');
}
# No output

To this:

switch('b') {
  case 'a':
    if(false) {
      die('failure');
    }
  case 'b':
    msg('success');
}
# Output 'success'

There are some scripts where this problem doesn't occur, and it's not clear what the difference is.

commented

Comment by LadyCailin

Undoubtably this is due to optimization issues. if(false){} will compile out, which means that in the following case:

switch(@a){
    case 'a':
        if(false){
            msg('hi');
        }
    case 'b':
        msg('boo');
}

you end up with the following equivalent (that is actually not equivalent):

switch(@a){
    case 'a':
    case 'b':
        msg('boo');
}

I'll have to look into this. I think I need to have two priorities of optimization, and let switch optimize before the code inside it, and automatically add breaks and such. As far as with returns/dies, this is likely because the condition is a terminal statement, which has special handling in the optimizer.

commented

Comment by PseudoKnight

Check. if(false){} is a bad testing method. I used it to see if die() had the same effect when nested, as it's not clear why some scripts are working fine with die() in switches. This is a strange compile optimization to me, as you'd never use it except in testing. If something evaluated to false every time the script ran, instead of optimizing it (hiding it), it should probably give a compile warning.

commented

Comment by LadyCailin

That's not good, actually. For instance, using the function_exists method. If you use a function that may or may not exist, the fact that the function doesn't exist isn't any sort of warning case. The following if statement will always be removed:

if(function_exists('blah')){
    blah();
}

Once I get const/final variables, the same thing should apply.

final/const @debug = false;
if(@debug){
    do_some_debug_logic();
}

Looking even further down the road, certain other values, such as compiler environment "constants" can be used to further optimize code, as well as support custom compiler errors, etc.

if(OS::isWindows()){
    windowsOnlyCode();
} else if(OS::isMac()){
    macOnlyCode();
} else if(OS::isLinux()){
    linuxOnlyCode();
} else {
    compiler_error('Unsupported OS');
}
commented

Comment by LadyCailin

This should be fixed in the latest commit.

commented

Comment by PseudoKnight

Oh, right, I forgot about compile time options. No regrets, though, because I like the last two examples.