py: Improve compiler syntax errors; catch more errors.
diff --git a/py/compile.c b/py/compile.c
index f1870bf..1fc5f07 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -69,8 +69,13 @@
     const emit_inline_asm_method_table_t *emit_inline_asm_method_table;   // current emit method table for inline asm
 } compiler_t;
 
-STATIC void compile_syntax_error(compiler_t *comp, const char *msg) {
+STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const char *msg) {
     // TODO store the error message to a variable in compiler_t instead of printing it
+    if (MP_PARSE_NODE_IS_STRUCT(pn)) {
+        printf("  File \"%s\", line " UINT_FMT "\n", qstr_str(comp->source_file), (machine_uint_t)((mp_parse_node_struct_t*)pn)->source_line);
+    } else {
+        printf("  File \"%s\"\n", qstr_str(comp->source_file));
+    }
     printf("SyntaxError: %s\n", msg);
     comp->had_error = true;
 }
@@ -351,7 +356,7 @@
                 case MP_TOKEN_KW_FALSE: vstr_printf(vstr, "False"); break;
                 case MP_TOKEN_KW_NONE: vstr_printf(vstr, "None"); break;
                 case MP_TOKEN_KW_TRUE: vstr_printf(vstr, "True"); break;
-                default: assert(0);
+                default: assert(0); // shouldn't happen
             }
             break;
         default: assert(0);
@@ -588,8 +593,7 @@
             pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
         }
         if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
-            compile_syntax_error(comp, "can't assign to function call");
-            return;
+            goto cannot_assign;
         } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
             if (assign_kind == ASSIGN_AUG_STORE) {
                 EMIT(rot_three);
@@ -615,18 +619,20 @@
                 EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
             }
         } else {
-            // shouldn't happen
-            assert(0);
+            goto cannot_assign;
         }
     } else {
-        // shouldn't happen
-        assert(0);
+        goto cannot_assign;
     }
 
     if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
-        // SyntaxError, cannot assign
-        assert(0);
+        goto cannot_assign;
     }
+
+    return;
+
+cannot_assign:
+    compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression");
 }
 
 void c_assign_tuple(compiler_t *comp, int n, mp_parse_node_t *nodes) {
@@ -638,7 +644,7 @@
                 EMIT_ARG(unpack_ex, i, n - i - 1);
                 have_star_index = i;
             } else {
-                compile_syntax_error(comp, "two starred expressions in assignment");
+                compile_syntax_error(comp, nodes[i], "two starred expressions in assignment");
                 return;
             }
         }
@@ -673,7 +679,7 @@
                     break;
             }
         } else {
-            compile_syntax_error(comp, "can't assign to literal");
+            compile_syntax_error(comp, pn, "can't assign to literal");
             return;
         }
     } else {
@@ -697,7 +703,7 @@
                 // lhs is something in parenthesis
                 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
                     // empty tuple
-                    compile_syntax_error(comp, "can't assign to ()");
+                    compile_syntax_error(comp, pn, "can't assign to ()");
                     return;
                 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
                     pns = (mp_parse_node_struct_t*)pns->nodes[0];
@@ -727,8 +733,8 @@
                 break;
 
             default:
-                printf("unknown assign, %u\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
-                assert(0);
+                compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression");
+                return;
         }
         return;
 
@@ -750,8 +756,9 @@
                     c_assign(comp, pns2->nodes[i], ASSIGN_STORE);
                 }
             } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
-                // TODO not implemented
-                assert(0);
+                // TODO can we ever get here? can it be compiled?
+                compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression");
+                return;
             } else {
                 // sequence with 2 items
                 goto sequence_with_2_items;
@@ -766,7 +773,7 @@
     return;
 
     bad_aug:
-    compile_syntax_error(comp, "illegal expression for augmented assignment");
+    compile_syntax_error(comp, pn, "illegal expression for augmented assignment");
 }
 
 // stuff for lambda and comprehensions and generators
@@ -841,6 +848,7 @@
             pn_equal = pns->nodes[2];
 
         } else {
+            // XXX what to do here?
             assert(0);
             return;
         }
@@ -850,7 +858,7 @@
 
             // check for non-default parameters given after default parameters (allowed by parser, but not syntactically valid)
             if (!comp->have_bare_star && comp->param_pass_num_default_params != 0) {
-                compile_syntax_error(comp, "non-default argument follows default argument");
+                compile_syntax_error(comp, pn, "non-default argument follows default argument");
                 return;
             }
 
@@ -988,7 +996,7 @@
     }
 
     if (name_len != 2) {
-        compile_syntax_error(comp, "invalid micropython decorator");
+        compile_syntax_error(comp, name_nodes[0], "invalid micropython decorator");
         return true;
     }
 
@@ -1006,7 +1014,7 @@
         *emit_options = MP_EMIT_OPT_ASM_THUMB;
 #endif
     } else {
-        compile_syntax_error(comp, "invalid micropython decorator");
+        compile_syntax_error(comp, name_nodes[1], "invalid micropython decorator");
     }
 
     return true;
@@ -1100,8 +1108,8 @@
                 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
             }
             if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
-                // SyntaxError: can't delete a function call
-                assert(0);
+                // can't delete function calls
+                goto cannot_delete;
             } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
                 compile_node(comp, pns1->nodes[0]);
                 EMIT(delete_subscr);
@@ -1109,17 +1117,14 @@
                 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
                 EMIT_ARG(delete_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
             } else {
-                // shouldn't happen
-                assert(0);
+                goto cannot_delete;
             }
         } else {
-            // shouldn't happen
-            assert(0);
+            goto cannot_delete;
         }
 
         if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
-            // SyntaxError, cannot delete
-            assert(0);
+            goto cannot_delete;
         }
     } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) {
         pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
@@ -1142,7 +1147,7 @@
                     }
                 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
                     // TODO not implemented; can't del comprehension?
-                    assert(0);
+                    goto cannot_delete;
                 } else {
                     // sequence with 2 items
                     goto sequence_with_2_items;
@@ -1158,9 +1163,14 @@
             c_del_stmt(comp, pn);
         }
     } else {
-        // not implemented
-        assert(0);
+        // TODO is there anything else to implement?
+        goto cannot_delete;
     }
+
+    return;
+
+cannot_delete:
+    compile_syntax_error(comp, (mp_parse_node_t)pn, "can't delete expression");
 }
 
 void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
@@ -1169,21 +1179,21 @@
 
 void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
     if (comp->break_label == 0) {
-        compile_syntax_error(comp, "'break' outside loop");
+        compile_syntax_error(comp, (mp_parse_node_t)pns, "'break' outside loop");
     }
     EMIT_ARG(break_loop, comp->break_label, comp->cur_except_level - comp->break_continue_except_level);
 }
 
 void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
     if (comp->continue_label == 0) {
-        compile_syntax_error(comp, "'continue' outside loop");
+        compile_syntax_error(comp, (mp_parse_node_t)pns, "'continue' outside loop");
     }
     EMIT_ARG(continue_loop, comp->continue_label, comp->cur_except_level - comp->break_continue_except_level);
 }
 
 void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
     if (comp->scope_cur->kind != SCOPE_FUNCTION) {
-        compile_syntax_error(comp, "'return' outside function");
+        compile_syntax_error(comp, (mp_parse_node_t)pns, "'return' outside function");
         return;
     }
     if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
@@ -1280,14 +1290,14 @@
         } else {
             // TODO not implemented
             // This covers relative imports starting with dot(s) like "from .foo import"
-            compile_syntax_error(comp, "Relative imports not implemented");
-            assert(0);
+            compile_syntax_error(comp, pn, "Relative imports not implemented");
+            return;
         }
     } else {
         // TODO not implemented
         // This covers relative imports with dots only like "from .. import"
-        compile_syntax_error(comp, "Relative imports not implemented");
-        assert(0);
+        compile_syntax_error(comp, pn, "Relative imports not implemented");
+        return;
     }
 }
 
@@ -1699,7 +1709,7 @@
         if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {
             // this is a catch all exception handler
             if (i + 1 != n_except) {
-                compile_syntax_error(comp, "default 'except:' must be last");
+                compile_syntax_error(comp, pn_excepts[i], "default 'except:' must be last");
                 return;
             }
         } else {
@@ -2090,10 +2100,7 @@
 }
 
 void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
-    // TODO
-    assert(0);
-    compile_node(comp, pns->nodes[0]);
-    //EMIT_ARG(unary_op, "UNARY_STAR");
+    compile_syntax_error(comp, (mp_parse_node_t)pns, "can use starred expression only as assignment target");
 }
 
 void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
@@ -2271,7 +2278,7 @@
         if (i == 0) {
             string_kind = pn_kind;
         } else if (pn_kind != string_kind) {
-            compile_syntax_error(comp, "cannot mix bytes and nonbytes literals");
+            compile_syntax_error(comp, (mp_parse_node_t)pns, "cannot mix bytes and nonbytes literals");
             return;
         }
         n_bytes += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
@@ -2431,13 +2438,13 @@
                     compile_node(comp, pn);
                     if (is_dict) {
                         if (!is_key_value) {
-                            compile_syntax_error(comp, "?expecting key:value for dictiona");
+                            compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting key:value for dictionary");
                             return;
                         }
                         EMIT(store_map);
                     } else {
                         if (is_key_value) {
-                            compile_syntax_error(comp, "?expecting just a value for s");
+                            compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting just a value for set");
                             return;
                         }
                     }
@@ -2557,7 +2564,7 @@
 
 void compile_arglist_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
     if (comp->have_star_arg) {
-        compile_syntax_error(comp, "?can't have multiple *x");
+        compile_syntax_error(comp, (mp_parse_node_t)pns, "can't have multiple *x");
         return;
     }
     comp->have_star_arg = true;
@@ -2566,7 +2573,7 @@
 
 void compile_arglist_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
     if (comp->have_dbl_star_arg) {
-        compile_syntax_error(comp, "?can't have multiple **x");
+        compile_syntax_error(comp, (mp_parse_node_t)pns, "can't have multiple **x");
         return;
     }
     comp->have_dbl_star_arg = true;
@@ -2578,7 +2585,7 @@
     mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
     if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_argument_3) {
         if (!MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
-            compile_syntax_error(comp, "?lhs of keyword argument must be an id");
+            compile_syntax_error(comp, (mp_parse_node_t)pns, "left-hand-side of keyword argument must be an id");
             return;
         }
         EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
@@ -2594,7 +2601,7 @@
 
 void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
     if (comp->scope_cur->kind != SCOPE_FUNCTION) {
-        compile_syntax_error(comp, "'yield' outside function");
+        compile_syntax_error(comp, (mp_parse_node_t)pns, "'yield' outside function");
         return;
     }
     if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
@@ -2658,7 +2665,7 @@
 #if MICROPY_DEBUG_PRINTERS
             mp_parse_node_print(pn, 0);
 #endif
-            assert(0);
+            compile_syntax_error(comp, pn, "internal compiler error");
         } else {
             f(comp, pns);
         }
@@ -2744,7 +2751,7 @@
         bool added;
         id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);
         if (!added) {
-            compile_syntax_error(comp, "?same name used for parameter");
+            compile_syntax_error(comp, pn, "same name used for parameter");
             return;
         }
         id_info->param = true;
@@ -3049,7 +3056,7 @@
         // emit instructions
         if (strcmp(qstr_str(op), "label") == 0) {
             if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
-                compile_syntax_error(comp, "inline assembler 'label' requires 1 argument");
+                compile_syntax_error(comp, nodes[i], "inline assembler 'label' requires 1 argument");
                 return;
             }
             int lab = comp_next_label(comp);