summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/mruby/irep.h5
-rw-r--r--src/codegen.c7
-rw-r--r--src/error.c56
3 files changed, 58 insertions, 10 deletions
diff --git a/include/mruby/irep.h b/include/mruby/irep.h
index 9ff523d33..0d8a05dbe 100644
--- a/include/mruby/irep.h
+++ b/include/mruby/irep.h
@@ -18,10 +18,13 @@ typedef struct mrb_irep {
int nregs;
mrb_code *iseq;
- short *lines;
mrb_value *pool;
mrb_sym *syms;
+ /* debug info */
+ const char *filename;
+ short *lines;
+
int ilen, plen, slen;
} mrb_irep;
diff --git a/src/codegen.c b/src/codegen.c
index 6197da33e..6dcc747c3 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -2074,6 +2074,9 @@ scope_finish(codegen_scope *s, int idx)
irep->syms = (mrb_sym *)codegen_realloc(s, s->syms, sizeof(mrb_sym)*s->slen);
irep->slen = s->slen;
}
+ if (s->filename) {
+ irep->filename = s->filename;
+ }
irep->nlocals = s->nlocals;
irep->nregs = s->nregs;
@@ -2479,12 +2482,12 @@ codegen_start(mrb_state *mrb, parser_state *p)
scope->filename = s;
}
if (setjmp(scope->jmp) != 0) {
- if (scope->filename) mrb_free(mrb, scope->filename);
+ //if (scope->filename) mrb_free(mrb, scope->filename);
return -1;
}
// prepare irep
codegen(scope, p->tree, NOVAL);
- if (scope->filename) mrb_free(mrb, scope->filename);
+ // if (scope->filename) mrb_free(mrb, scope->filename);
mrb_pool_close(scope->mpool);
return 0;
}
diff --git a/src/error.c b/src/error.c
index 412a63d3e..444a088c9 100644
--- a/src/error.c
+++ b/src/error.c
@@ -13,6 +13,8 @@
#include "mruby/variable.h"
#include "mruby/string.h"
#include "mruby/class.h"
+#include "mruby/proc.h"
+#include "mruby/irep.h"
#define warn_printf printf
@@ -121,14 +123,32 @@ exc_message(mrb_state *mrb, mrb_value exc)
static mrb_value
exc_inspect(mrb_state *mrb, mrb_value exc)
{
- mrb_value str;
-
- str = mrb_str_new2(mrb, mrb_obj_classname(mrb, exc));
- exc = mrb_obj_as_string(mrb, exc);
-
- if (RSTRING_LEN(exc) > 0) {
+ mrb_value str, mesg, file, line;
+
+ mesg = mrb_attr_get(mrb, exc, mrb_intern(mrb, "mesg"));
+ file = mrb_attr_get(mrb, exc, mrb_intern(mrb, "file"));
+ line = mrb_attr_get(mrb, exc, mrb_intern(mrb, "line"));
+
+ if (!mrb_nil_p(file) && !mrb_nil_p(line)) {
+ str = file;
+ mrb_str_cat2(mrb, str, ":");
+ mrb_str_append(mrb, str, line);
mrb_str_cat2(mrb, str, ": ");
- mrb_str_append(mrb, str, exc);
+ if (RSTRING_LEN(mesg) > 0) {
+ mrb_str_append(mrb, str, mesg);
+ mrb_str_cat2(mrb, str, " (");
+ }
+ mrb_str_cat2(mrb, str, mrb_obj_classname(mrb, exc));
+ if (RSTRING_LEN(mesg) > 0) {
+ mrb_str_cat2(mrb, str, ")");
+ }
+ }
+ else {
+ str = mrb_str_new2(mrb, mrb_obj_classname(mrb, exc));
+ if (RSTRING_LEN(mesg) > 0) {
+ mrb_str_cat2(mrb, str, ": ");
+ mrb_str_append(mrb, str, mesg);
+ }
}
return str;
}
@@ -160,10 +180,32 @@ exc_equal(mrb_state *mrb, mrb_value exc)
return mrb_true_value();
}
+static void
+exc_debug_info(mrb_state *mrb, struct RObject *exc)
+{
+ mrb_callinfo *ci = mrb->ci;
+ mrb_code *pc = ci->pc;
+
+ while (ci >= mrb->cibase) {
+ if (!pc && ci->pc) pc = ci->pc;
+ if (ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) {
+ mrb_irep *irep = ci->proc->body.irep;
+
+ if (irep->lines && irep->iseq <= pc && pc < irep->iseq + irep->ilen) {
+ mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "file"), mrb_str_new_cstr(mrb, irep->filename));
+ mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "line"), mrb_fixnum_value(irep->lines[pc - irep->iseq - 1]));
+ return;
+ }
+ }
+ ci--;
+ }
+}
+
void
mrb_exc_raise(mrb_state *mrb, mrb_value exc)
{
mrb->exc = (struct RObject*)mrb_object(exc);
+ exc_debug_info(mrb, mrb->exc);
if (!mrb->jmp) {
abort();
}