From 697e80cb16ef40698fbccb876e73a8fe57dabf0a Mon Sep 17 00:00:00 2001 From: Sei Lisa Date: Sat, 7 May 2016 02:38:54 +0200 Subject: [PATCH] Rather than reproduce the broken behaviour, throw an error on missing default. Changed my mind. This looks saner. Now, if the 'default:' label is missing, an error will be thrown by default. It has to be explicitly disabled if normal C-like behaviour is desired (namely to jump to the 'break' label if no condition is met). --- lslopt/lslparse.py | 26 ++++++++++++++++---------- main.py | 9 +++------ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/lslopt/lslparse.py b/lslopt/lslparse.py index f4acebf..7d7edcf 100644 --- a/lslopt/lslparse.py +++ b/lslopt/lslparse.py @@ -148,6 +148,12 @@ class EParseManyDefaults(EParse): super(EParseManyDefaults, self).__init__(parser, u"multiple 'default' labels inside 'switch' statement") +class EParseMissingDefault(EParse): + def __init__(self, parser): + super(EParseMissingDefault, self).__init__(parser, + u"Missing 'default:' label inside 'switch' statement; disable" + u" option 'errmissingdefault' to disable this error.") + class EParseInvalidBreak(EParse): def __init__(self, parser): super(EParseInvalidBreak, self).__init__(parser, @@ -1674,15 +1680,15 @@ list lazy_list_set(list L, integer i, list v) ]}) if switchcasedefault is None: - warning("No 'default:' label in switch statement") - if self.brokennodefault: - warning("Broken behaviour active - falling through") - if not self.brokennodefault: - switchcasedefault = brk - self.breakstack[-1][2] = True - if switchcasedefault is not None: - prelude.append({'nt':'JUMP', 't':None, 'name':switchcasedefault, - 'scope':blkscope}) + if self.errmissingdefault: + raise EParseMissingDefault(self) + switchcasedefault = brk + self.breakstack[-1][2] = True + # TODO: Check if this JUMP is necessary + # (it won't be if the default label is the next instruction) + # This is arguably better done after DCR. + prelude.append({'nt':'JUMP', 't':None, 'name':switchcasedefault, + 'scope':blkscope}) last = self.breakstack.pop() if last[2]: blk.append({'nt':'@', 'name':brk, 'scope':blkscope}) @@ -2317,7 +2323,7 @@ list lazy_list_set(list L, integer i, list v) self.keywords |= frozenset(('switch', 'case', 'break')) # Broken behaviour in the absence of a default: label in a switch stmt. - self.brokennodefault = 'brokennodefault' in options + self.errmissingdefault = 'errmissingdefault' in options # Allow brackets for assignment of list elements e.g. mylist[5]=4 self.lazylists = 'lazylists' in options diff --git a/main.py b/main.py index 88deec2..86ee201 100755 --- a/main.py +++ b/main.py @@ -228,11 +228,6 @@ Optimizer options (+ means active by default, - means inactive by default): will go to the last label with that name). This flag works around that limitation by replacing the names of the labels in the output with unique ones. - brokennodefault + Mimic Firestorm's legacy broken behaviour when the - 'default' label in a switch statement is absent. Rather - than jumping to the end of the switch in that case - (which is how it behaves when this option is not set), - it falls through and executes the first 'case' label. Deprecated / compatibility syntax extensions options: @@ -247,6 +242,8 @@ Optimizer options (+ means active by default, - means inactive by default): Like lazylists, it's implemented for compatibility with Firestorm, but not recommended. Note that the operand to switch() may be evaluated more than once. + errmissingdefault + Throw an error in case the 'default:' label of a switch + statement is missing. funcoverride - Allow duplicate function definitions to override the previous definition. For compatibility with Firestorm's optimizer. @@ -305,7 +302,7 @@ def main(): # Default options options = set(('extendedglobalexpr','extendedtypecast','extendedassignment', 'allowkeyconcat','allowmultistrings','skippreproc','optimize', - 'optsigns','optfloats','constfold','dcr', 'brokennodefault', + 'optsigns','optfloats','constfold','dcr','errmissingdefault', )) try: