diff --git a/lslopt/lslparse.py b/lslopt/lslparse.py index 7d7edcf..1636ada 100644 --- a/lslopt/lslparse.py +++ b/lslopt/lslparse.py @@ -545,6 +545,19 @@ class parser(object): raise EParseUEOF(self) raise EParseSyntax(self) + def does_something(self, blk): + """Tell if a list of nodes does something or is just empty statements + (a pure combination of ';' and '{}' and '@') + """ + for node in blk: + if '@' != node['nt'] != ';': + if node['nt'] == '{}': + if self.does_something(node['ch']): + return True + else: + return True + return False + def Parse_vector_rotation_tail(self): """(See Parse_unary_postfix_expression for context) @@ -1682,13 +1695,25 @@ list lazy_list_set(list L, integer i, list v) if switchcasedefault is None: 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}) + # Check if it's worth adding a break. If there's no executable + # code, there's no point. However, this check is insufficient. + # It misses SEF expressions. For that reason, this is best left + # up to a later optimizer that knows about SEF. But we do a + # preliminary elimination here. + if self.does_something(blk): + switchcasedefault = brk + self.breakstack[-1][2] = True + else: + # TODO: Keep checking until there's output-generating code. + # For example, this isn't optimized due to the semicolon: + # switch(1) { ; default: 1; } + if blk and blk[0]['nt'] == '@' and blk[0]['name'] == switchcasedefault: + switchcasedefault = None + del blk[0] + + if switchcasedefault is not None: + prelude.append({'nt':'JUMP', 't':None, 'name':switchcasedefault, + 'scope':blkscope}) last = self.breakstack.pop() if last[2]: blk.append({'nt':'@', 'name':brk, 'scope':blkscope})