Add source file name and line number to error messages.

Byte code has a map from byte-code offset to source-code line number,
used to give better error messages.
diff --git a/py/objexcept.c b/py/objexcept.c
index 1d30758..7f87478 100644
--- a/py/objexcept.c
+++ b/py/objexcept.c
@@ -17,6 +17,8 @@
 // have args tuple (or otherwise have it as NULL).
 typedef struct mp_obj_exception_t {
     mp_obj_base_t base;
+    qstr source_file;
+    machine_uint_t source_line;
     qstr id;
     qstr msg;
     mp_obj_tuple_t args;
@@ -87,6 +89,8 @@
     // make exception object
     mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t*, 0);
     o->base.type = &exception_type;
+    o->source_file = 0;
+    o->source_line = 0;
     o->id = id;
     o->args.len = 0;
     if (fmt == NULL) {
@@ -109,3 +113,23 @@
     mp_obj_exception_t *self = self_in;
     return self->id;
 }
+
+void mp_obj_exception_set_source_info(mp_obj_t self_in, qstr file, machine_uint_t line) {
+    assert(MP_OBJ_IS_TYPE(self_in, &exception_type));
+    mp_obj_exception_t *self = self_in;
+    // TODO make a list of file/line pairs for the traceback
+    // for now, just keep the first one
+    if (file != 0 && self->source_file == 0) {
+        self->source_file = file;
+    }
+    if (line != 0 && self->source_line == 0) {
+        self->source_line = line;
+    }
+}
+
+void mp_obj_exception_get_source_info(mp_obj_t self_in, qstr *file, machine_uint_t *line) {
+    assert(MP_OBJ_IS_TYPE(self_in, &exception_type));
+    mp_obj_exception_t *self = self_in;
+    *file = self->source_file;
+    *line = self->source_line;
+}