feature request: $nextcase and $break in compile-time $switch
A fallthrough and break option for compile-time switch statements should be included to control flow with compile-time values.
e.g. ...
$switch ($ct_argstype[($argidx / 3)]) :
$case OptionArgType.EXPLICIT_NONE: $break;
$case OptionArgType.FLAG: *($vaarg[$argidx + 2]) = true;
$case OptionArgType.INCREMENTAL: *($vaarg[$argidx + 2]) = *($vaarg[$argidx + 2]) + 1;
$case OptionArgType.OPTIONAL_ARGUMENT:
if (null != opt::arg.ptr) break CT_SWITCH;
$nextcase;
$case OptionArgType.REQUIRED_ARGUMENT:
if (null == opt::arg.ptr || !opt::arg.len) return MISSING_ARGUMENT?;
// etc...
$endswitch
As we talked about before on the discord, this is currently not planned. I would like to keep the compile time meta language to be as simplistic as possible, which means that sometimes useful features are omitted. Possibly we could add $goto and $label FOO though, if people have important use-cases for it. But my thought is that if it is complex enough then maybe compile time code isn't the right place for it, and instead one could then use $exec and project exec to generate that code?
I think that's entirely sensible, given the extra complexities that compile-time evaluation can introduce as well as the added sluggishness to c3c, which I understand is important to limit carefully.
I do believe that $goto and $label will actually resolve all related flow control meta-language feature requests if you're able to implement them. You could well consider anyone's reasons for $nextcase, $break, $continue, etc. as all use-cases solvable by those two statements. This also removes the need for some of the more hacky solutions around labeled runtime if/while LABEL: (true) type statements with compile-time-wrapped break/continue LABEL statements.
And then with $goto + $label, questions of $exec could still remain a separate discussion and have a less coupled set of use-cases.
So something like:
$for $i = 0; $i < 10; $i++:
$if $i > CONST:
$goto LABEL;
$endif
$endfor
$label LABEL:
$switch $a:
$case int:
$b[$j++] = 1;
$goto NEXT;
$case double:
$label NEXT:
$b[$j++] = foo();
$endswitch;
There are problems with the semantics of this. Consider the following two:
$for var $i = 0; $i < 3; $i++:
{
int a = 0;
$if @foo($i) == 0:
$break; // Break inside a runtime block
$endif
test(&a);
}
$endfor
$if @foo(BAR):
$goto $FOO; // Jumping into a loop
$endif
int x;
$for var $i = 0; $i < 3; $i++:
$FOO:
test();
$endfor
Both have questionable semantics. Even this is not straightforward:
$switch @foo($i):
$case 1:
foo();
$goto $BAR;
$case 2:
baz();
$BAR:
bar();
$endswitch
If $goto can only jump OUT of a compile time scope, and to the beginning of a $case, then it would more straightforward. But the complexity of it makes me wonder whether it's sufficiently important.