From d2d64f00fb7f1487c1fa21a456e003a801d7e711 Mon Sep 17 00:00:00 2001
From: Damien George <damien.p.george@gmail.com>
Date: Wed, 14 Jan 2015 21:32:42 +0000
Subject: [PATCH] py: Add "default" to switches to allow better code flow
 analysis.

This helps compiler produce smaller code.  Saves 124 bytes on stmhal and
bare-arm.
---
 py/compile.c      | 10 ++++------
 py/emitbc.c       |  3 ++-
 py/emitglue.c     |  3 ++-
 py/objdict.c      |  5 +----
 py/objfun.c       |  5 +----
 py/objgenerator.c | 11 ++---------
 py/parse.c        |  8 +++++++-
 7 files changed, 19 insertions(+), 26 deletions(-)

diff --git a/py/compile.c b/py/compile.c
index 55ab68896..f55485425 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -860,6 +860,7 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_
                     EMIT_ARG(store_id, arg);
                     break;
                 case ASSIGN_AUG_LOAD:
+                default:
                     EMIT_ARG(load_id, arg);
                     break;
             }
@@ -2185,8 +2186,7 @@ STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
                 case MP_TOKEN_DEL_DBL_SLASH_EQUAL: op = MP_BINARY_OP_INPLACE_FLOOR_DIVIDE; break;
                 case MP_TOKEN_DEL_SLASH_EQUAL: op = MP_BINARY_OP_INPLACE_TRUE_DIVIDE; break;
                 case MP_TOKEN_DEL_PERCENT_EQUAL: op = MP_BINARY_OP_INPLACE_MODULO; break;
-                case MP_TOKEN_DEL_DBL_STAR_EQUAL: op = MP_BINARY_OP_INPLACE_POWER; break;
-                default: assert(0); op = MP_BINARY_OP_INPLACE_OR; // shouldn't happen
+                case MP_TOKEN_DEL_DBL_STAR_EQUAL: default: op = MP_BINARY_OP_INPLACE_POWER; break;
             }
             EMIT_ARG(binary_op, op);
             c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign
@@ -2350,8 +2350,7 @@ STATIC void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
                 case MP_TOKEN_OP_LESS_EQUAL: op = MP_BINARY_OP_LESS_EQUAL; break;
                 case MP_TOKEN_OP_MORE_EQUAL: op = MP_BINARY_OP_MORE_EQUAL; break;
                 case MP_TOKEN_OP_NOT_EQUAL: op = MP_BINARY_OP_NOT_EQUAL; break;
-                case MP_TOKEN_KW_IN: op = MP_BINARY_OP_IN; break;
-                default: assert(0); op = MP_BINARY_OP_LESS; // shouldn't happen
+                case MP_TOKEN_KW_IN: default: op = MP_BINARY_OP_IN; break;
             }
             EMIT_ARG(binary_op, op);
         } else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])) {
@@ -2982,7 +2981,7 @@ STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) {
             case MP_PARSE_NODE_DECIMAL: EMIT_ARG(load_const_dec, arg); break;
             case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg, false); break;
             case MP_PARSE_NODE_BYTES: EMIT_ARG(load_const_str, arg, true); break;
-            case MP_PARSE_NODE_TOKEN:
+            case MP_PARSE_NODE_TOKEN: default:
                 if (arg == MP_TOKEN_NEWLINE) {
                     // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
                     // or when single_input lets through a NEWLINE (user enters a blank line)
@@ -2991,7 +2990,6 @@ STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) {
                   EMIT_ARG(load_const_tok, arg);
                 }
                 break;
-            default: assert(0);
         }
     } else {
         mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
diff --git a/py/emitbc.c b/py/emitbc.c
index d63739125..436fdf143 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -454,8 +454,9 @@ STATIC void emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
         case MP_TOKEN_KW_FALSE: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_FALSE); break;
         case MP_TOKEN_KW_NONE: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_NONE); break;
         case MP_TOKEN_KW_TRUE: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_TRUE); break;
+        no_other_choice:
         case MP_TOKEN_ELLIPSIS: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_ELLIPSIS); break;
-        default: assert(0);
+        default: assert(0); goto no_other_choice; // to help flow control analysis
     }
 }
 
diff --git a/py/emitglue.c b/py/emitglue.c
index 65d131125..587c738ac 100644
--- a/py/emitglue.c
+++ b/py/emitglue.c
@@ -110,6 +110,7 @@ mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp
     mp_obj_t fun;
     switch (rc->kind) {
         case MP_CODE_BYTECODE:
+        no_other_choice:
             fun = mp_obj_new_fun_bc(rc->scope_flags, rc->n_pos_args, rc->n_kwonly_args, def_args, def_kw_args, rc->u_byte.code);
             break;
         #if MICROPY_EMIT_NATIVE
@@ -128,7 +129,7 @@ mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp
         default:
             // raw code was never set (this should not happen)
             assert(0);
-            return mp_const_none;
+            goto no_other_choice; // to help flow control analysis
     }
 
     // check for generator functions and if so wrap in generator object
diff --git a/py/objdict.c b/py/objdict.c
index 63b3cfb32..900ecf4eb 100644
--- a/py/objdict.c
+++ b/py/objdict.c
@@ -415,7 +415,7 @@ STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
     } else {
         switch (self->kind) {
             case MP_DICT_VIEW_ITEMS:
-            {
+            default: {
                 mp_obj_t items[] = {next->key, next->value};
                 return mp_obj_new_tuple(2, items);
             }
@@ -423,9 +423,6 @@ STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
                 return next->key;
             case MP_DICT_VIEW_VALUES:
                 return next->value;
-            default:
-                assert(0);          /* can't happen */
-                return mp_const_none;
         }
     }
 }
diff --git a/py/objfun.c b/py/objfun.c
index 6ef12c910..8f835726d 100644
--- a/py/objfun.c
+++ b/py/objfun.c
@@ -83,11 +83,8 @@ STATIC mp_obj_t fun_builtin_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n
                 return ((mp_fun_2_t)self->fun)(args[0], args[1]);
 
             case 3:
-                return ((mp_fun_3_t)self->fun)(args[0], args[1], args[2]);
-
             default:
-                assert(0);
-                return mp_const_none;
+                return ((mp_fun_3_t)self->fun)(args[0], args[1], args[2]);
         }
 
     } else {
diff --git a/py/objgenerator.c b/py/objgenerator.c
index 1b06975c9..a4d22aa8d 100644
--- a/py/objgenerator.c
+++ b/py/objgenerator.c
@@ -120,6 +120,7 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_
 
     switch (ret_kind) {
         case MP_VM_RETURN_NORMAL:
+        default:
             // Explicitly mark generator as completed. If we don't do this,
             // subsequent next() may re-execute statements after last yield
             // again and again, leading to side effects.
@@ -137,11 +138,6 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_
             self->code_state.ip = 0;
             *ret_val = self->code_state.state[self->code_state.n_state - 1];
             break;
-
-        default:
-            assert(0);
-            *ret_val = mp_const_none;
-            break;
     }
 
     return ret_kind;
@@ -151,6 +147,7 @@ STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_o
     mp_obj_t ret;
     switch (mp_obj_gen_resume(self_in, send_value, throw_value, &ret)) {
         case MP_VM_RETURN_NORMAL:
+        default:
             // Optimize return w/o value in case generator is used in for loop
             if (ret == mp_const_none || ret == MP_OBJ_STOP_ITERATION) {
                 return MP_OBJ_STOP_ITERATION;
@@ -173,10 +170,6 @@ STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_o
             } else {
                 nlr_raise(ret);
             }
-
-        default:
-            assert(0);
-            return mp_const_none;
     }
 }
 
diff --git a/py/parse.c b/py/parse.c
index 6d2108dca..c60bbb17e 100644
--- a/py/parse.c
+++ b/py/parse.c
@@ -456,11 +456,13 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
                             }
                             break;
                         case RULE_ARG_RULE:
+                        rule_or_no_other_choice:
                             push_rule(&parser, rule_src_line, rule, i + 1); // save this or-rule
                             push_rule_from_arg(&parser, rule->arg[i]); // push child of or-rule
                             goto next_rule;
                         default:
                             assert(0);
+                            goto rule_or_no_other_choice; // to help flow control analysis
                     }
                 }
                 if ((rule->arg[i] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
@@ -520,14 +522,16 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
                                 }
                             }
                             break;
-                                           }
+                        }
                         case RULE_ARG_RULE:
                         case RULE_ARG_OPT_RULE:
+                        rule_and_no_other_choice:
                             push_rule(&parser, rule_src_line, rule, i + 1); // save this and-rule
                             push_rule_from_arg(&parser, rule->arg[i]); // push child of and-rule
                             goto next_rule;
                         default:
                             assert(0);
+                            goto rule_and_no_other_choice; // to help flow control analysis
                     }
                 }
 
@@ -674,11 +678,13 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
                                 }
                                 break;
                             case RULE_ARG_RULE:
+                            rule_list_no_other_choice:
                                 push_rule(&parser, rule_src_line, rule, i + 1); // save this list-rule
                                 push_rule_from_arg(&parser, arg); // push child of list-rule
                                 goto next_rule;
                             default:
                                 assert(0);
+                                goto rule_list_no_other_choice; // to help flow control analysis
                         }
                     }
                 }
-- 
GitLab