diff --git a/moo/kernel/Context.moo b/moo/kernel/Context.moo index 51e355b..5ca3ecc 100644 --- a/moo/kernel/Context.moo +++ b/moo/kernel/Context.moo @@ -346,4 +346,11 @@ class(#pointer) CompiledMethod(Object) { ^self.name } + + method(#primitive) sourceFile. + + method sourceLine + { + ^self.source_line + } } diff --git a/moo/kernel/Except.moo b/moo/kernel/Except.moo index 3c0a8d6..063a0b8 100644 --- a/moo/kernel/Except.moo +++ b/moo/kernel/Except.moo @@ -74,7 +74,7 @@ System logNl: "== BACKTRACE ==". ctx := thisContext. while (ctx notNil) { - if (ctx class == MethodContext) { System logNl: (" " & ctx method owner name & ">>" & ctx method name) }. + if (ctx class == MethodContext) { System logNl: (" " & ctx method owner name & ">>" & ctx method name & " (" & ctx method sourceFile & " " & ctx method sourceLine asString & ")"). }. // TODO: include blockcontext??? ctx := ctx sender. }. diff --git a/moo/lib/comp.c b/moo/lib/comp.c index e808bb4..3d2f405 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -459,7 +459,7 @@ static int copy_string_to (moo_t* moo, const moo_oocs_t* src, moo_oocs_t* dst, m capa = MOO_ALIGN(len, CLASS_BUFFER_ALIGN); - tmp = moo_reallocmem(moo, dst->ptr, MOO_SIZEOF(*tmp) * capa); + tmp = (moo_ooch_t*)moo_reallocmem(moo, dst->ptr, MOO_SIZEOF(*tmp) * capa); if (!tmp) return -1; dst->ptr = tmp; @@ -4158,6 +4158,8 @@ static int compile_method_name (moo_t* moo, moo_method_data_t* mth) * unary-selector := identifier */ int n; + static moo_ooch_t _nul = '\0'; + moo_oocs_t dummy; MOO_ASSERT (moo, mth->tmpr_count == 0); @@ -4180,22 +4182,28 @@ static int compile_method_name (moo_t* moo, moo_method_data_t* mth) /* illegal method name */ moo_setsynerr (moo, MOO_SYNERR_MTHNAME, TOKEN_LOC(moo), TOKEN_NAME(moo)); n = -1; + break; } - if (n >= 0) - { - if (method_exists(moo, &mth->name)) - { - moo_setsynerr (moo, MOO_SYNERR_MTHNAMEDUPL, &mth->name_loc, &mth->name); - return -1; - } + if (n <= -1) return -1; - /* compile_unary_method_name() returns 9999 if the name is followed by () */ - if (mth->variadic && n != 9999) - { - moo_setsynerr (moo, MOO_SYNERR_VARIADMTHINVAL, &mth->name_loc, &mth->name); - return -1; - } + /* null terminate it for convenience */ + dummy.ptr = &_nul; + dummy.len = 1; + if (add_method_name_fragment(moo, mth, &dummy) <= -1) return -1; + mth->name.len--; /* restore the method name length back */ + + if (method_exists(moo, &mth->name)) + { + moo_setsynerr (moo, MOO_SYNERR_MTHNAMEDUPL, &mth->name_loc, &mth->name); + return -1; + } + + /* compile_unary_method_name() returns 9999 if the name is followed by () */ + if (mth->variadic && n != 9999) + { + moo_setsynerr (moo, MOO_SYNERR_VARIADMTHINVAL, &mth->name_loc, &mth->name); + return -1; } MOO_ASSERT (moo, mth->tmpr_nargs < MAX_CODE_NARGS); @@ -4203,7 +4211,7 @@ static int compile_method_name (moo_t* moo, moo_method_data_t* mth) * arguments after having processed the message pattern. it's because * moo treats arguments the same as temporaries */ mth->tmpr_count = mth->tmpr_nargs; - return n; + return 0; } static int compile_method_temporaries (moo_t* moo) @@ -6997,6 +7005,42 @@ static int add_compiled_method (moo_t* moo) * Just set it to 0 to indicate that the information is not available */ mth->source_line = MOO_SMOOI_TO_OOP(0); } + + if (moo->dbginfo) + { + moo_oow_t file_offset; + moo_oow_t class_offset; + moo_oow_t method_offset; + + if (cc->mth.code_start_loc.file) + { + if (moo_addfiletodbginfo(moo, cc->mth.code_start_loc.file, &file_offset) <= -1) + { + /* TODO: warning */ + file_offset = 0; + } + else if (file_offset > MOO_SMOOI_MAX) + { + /* TODO: warnign */ + file_offset = 0; + } + } + else + { + /* main stream */ + file_offset = 0; + } + mth->source_file = MOO_SMOOI_TO_OOP(file_offset); + +/* TODO: call moo_addclasstodbginfo() */ + class_offset = 0; + + if (moo_addmethodtodbginfo(moo, file_offset, class_offset, cc->mth.name.ptr, cc->mth.code.locptr, cc->mth.code.len, &method_offset) <= -1) + { + /* TODO: warning. no debug information about this method will be available */ + } + } + /*TODO: preserve source??? mth->text = cc->mth.text the compiler must collect all source method string collected so far. need to write code to collect string. diff --git a/moo/lib/debug.c b/moo/lib/debug.c index ff8d469..93ff282 100644 --- a/moo/lib/debug.c +++ b/moo/lib/debug.c @@ -132,7 +132,8 @@ int moo_addfiletodbginfo (moo_t* moo, const moo_ooch_t* file_name, moo_oow_t* st if (moo->dbginfo->_last_file > 0) { - moo_oow_t offset = moo->dbginfo->_last_fiel; + /* TODO: avoid linear search. need indexing for speed up */ + moo_oow_t offset = moo->dbginfo->_last_file; do { di = &((moo_uint8_t*)moo->dbginfo)[offset]; @@ -173,6 +174,23 @@ int moo_addclasstodbginfo (moo_t* moo, const moo_ooch_t* class_name, moo_oow_t f if (!moo->dbginfo) return 0; /* debug information is disabled*/ + if (moo->dbginfo->_last_class > 0) + { + /* TODO: avoid linear search. need indexing for speed up */ + moo_oow_t offset = moo->dbginfo->_last_class; + do + { + di = &((moo_uint8_t*)moo->dbginfo)[offset]; + if (moo_comp_oocstr(di + 1, class_name) == 0 && di->_file == file_offset && di->_line == file_line) + { + if (start_offset) *start_offset = offset; + return 0; + } + offset = di->_next; + } + while (offset > 0); + } + name_len = moo_count_oocstr(class_name); name_bytes = (name_len + 1) * MOO_SIZEOF(*class_name); name_bytes_aligned = MOO_ALIGN_POW2(name_bytes, MOO_SIZEOF_OOW_T); @@ -195,7 +213,7 @@ int moo_addclasstodbginfo (moo_t* moo, const moo_ooch_t* class_name, moo_oow_t f return 0; } -int moo_addmethodtodbginfo (moo_t* moo, moo_oow_t file_offset, moo_oow_t class_offset, const moo_ooch_t* method_name, const moo_oow_t* code_loc_ptr, moo_oow_t code_loc_len) +int moo_addmethodtodbginfo (moo_t* moo, moo_oow_t file_offset, moo_oow_t class_offset, const moo_ooch_t* method_name, const moo_oow_t* code_loc_ptr, moo_oow_t code_loc_len, moo_oow_t* start_offset) { moo_oow_t name_len, name_bytes, name_bytes_aligned, code_loc_bytes, code_loc_bytes_aligned, req_bytes; moo_dbginfo_method_t* di; @@ -225,6 +243,6 @@ int moo_addmethodtodbginfo (moo_t* moo, moo_oow_t file_offset, moo_oow_t class_o moo->dbginfo->_last_method = moo->dbginfo->_len; moo->dbginfo->_len += req_bytes; - /*if (start_offset) *start_offset = moo->dbginfo->_last_method;*/ + if (start_offset) *start_offset = moo->dbginfo->_last_method; return 0; } diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 343f6d1..8ce52f5 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -2215,6 +2215,39 @@ static moo_pfrc_t pf_context_find_exception_handler (moo_t* moo, moo_mod_t* mod, return MOO_PF_SUCCESS; } +/* ------------------------------------------------------------------ */ +static moo_pfrc_t pf_method_get_source_file (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) +{ + moo_oop_method_t rcv; + moo_oop_t tmp; + + if (moo->dbginfo) + { +/* TODO: return sothing else lighter-weight than a string? */ + rcv = (moo_oop_method_t*)MOO_STACK_GETRCV(moo, nargs); + if (rcv->source_file == MOO_SMOOI_TO_OOP(0)) + { +/* TOOD: use the actual name as given by the caller ? */ + tmp = moo_makestringwithbchars(moo, "
", 6); + } + else + { + moo_dbginfo_file_t* di; + di = (moo_dbginfo_file_t*)&((moo_uint8_t*)moo->dbginfo)[MOO_OOP_TO_SMOOI(rcv->source_file)]; + tmp = moo_makestring(moo, di + 1, moo_count_oocstr(di + 1)); + } + if (!tmp) return MOO_PF_FAILURE; + + MOO_STACK_SETRET (moo, nargs, tmp); + } + else + { + MOO_STACK_SETRET (moo, nargs, moo->_nil); + } + + return MOO_PF_SUCCESS; +} + /* ------------------------------------------------------------------ */ static moo_pfrc_t __block_value (moo_t* moo, moo_oop_context_t rcv_blkctx, moo_ooi_t nargs, moo_ooi_t num_first_arg_elems, moo_oop_context_t* pblkctx) @@ -3938,6 +3971,8 @@ static pf_t pftab[] = { "Character_asError", { pf_character_as_error, 0, 0 } }, { "Character_asInteger", { pf_character_as_smooi, 0, 0 } }, + { "CompiledMethod_sourceFile", { pf_method_get_source_file, 0, 0 } }, + { "Error_asCharacter", { pf_error_as_character, 0, 0 } }, { "Error_asInteger", { pf_error_as_integer, 0, 0 } }, { "Error_asString", { pf_error_as_string, 0, 0 } }, diff --git a/moo/lib/moo-prv.h b/moo/lib/moo-prv.h index f5e84d6..43306b1 100644 --- a/moo/lib/moo-prv.h +++ b/moo/lib/moo-prv.h @@ -1665,6 +1665,10 @@ moo_pfrc_t moo_pf_uc_to_utf8 (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs); void moo_dumpsymtab (moo_t* moo); void moo_dumpdic (moo_t* moo, moo_oop_dic_t dic, const moo_bch_t* title); +int moo_addfiletodbginfo (moo_t* moo, const moo_ooch_t* file_name, moo_oow_t* start_offset); +int moo_addclasstodbginfo (moo_t* moo, const moo_ooch_t* class_name, moo_oow_t file_offset, moo_oow_t file_line, moo_oow_t* start_offset); +int moo_addmethodtodbginfo (moo_t* moo, moo_oow_t file_offset, moo_oow_t class_offset, const moo_ooch_t* method_name, const moo_oow_t* code_loc_ptr, moo_oow_t code_loc_len, moo_oow_t* start_offset); + #if defined(__cplusplus) } diff --git a/moo/lib/moo.h b/moo/lib/moo.h index 4fc421b..4d4b6ec 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -586,7 +586,7 @@ struct moo_method_t #endif moo_oop_t source_text; /* source text. String if available. nil if not */ - moo_oop_t source_file; /* source file path that contains the definition of this method. String if available. nil for the main source stream */ + moo_oop_t source_file; /* SmallInteger. source file path that contains the definition of this method. offset from moo->dbginfo. 0 for the main stream. */ moo_oop_t source_line; /* SmallInteger. line of the source file where the method definition begins. valid only if source_file is not nil */ /* == variable indexed part == */