diff --git a/compile.c b/compile.c index 9c2bbcf..d9b5937 100644 --- a/compile.c +++ b/compile.c @@ -2950,8 +2950,9 @@ CORD compile(env_t *env, ast_t *ast) env->code->function_naming = CORD_all( env->code->function_naming, - CORD_asprintf("register_function(%r, Text(%r \" [%s.tm:%ld]\"));\n", - name, CORD_quoted(type_to_cord(get_type(env, ast))), file_base_name(ast->file->filename), get_line_number(ast->file, ast->start))); + CORD_asprintf("register_function(%r, Text(\"%s.tm\"), %ld, Text(%r));\n", + name, file_base_name(ast->file->filename), get_line_number(ast->file, ast->start), + CORD_quoted(type_to_cord(get_type(env, ast))))); env_t *body_scope = fresh_scope(env); body_scope->deferred = NULL; @@ -4225,8 +4226,8 @@ CORD compile_function(env_t *env, ast_t *ast, CORD *staticdefs) if (!fndef->is_inline) { env->code->function_naming = CORD_all( env->code->function_naming, - CORD_asprintf("register_function(%r, Text(%r \" [%s.tm:%ld]\"));\n", - name, CORD_quoted(text), file_base_name(ast->file->filename), get_line_number(ast->file, ast->start))); + CORD_asprintf("register_function(%r, Text(\"%s.tm\"), %ld, Text(%r));\n", + name, file_base_name(ast->file->filename), get_line_number(ast->file, ast->start), CORD_quoted(text))); } return definition; } diff --git a/stdlib/functiontype.c b/stdlib/functiontype.c index b62ef2a..dc4d0c9 100644 --- a/stdlib/functiontype.c +++ b/stdlib/functiontype.c @@ -4,21 +4,70 @@ #include "datatypes.h" #include "functiontype.h" +#include "optionals.h" +#include "structs.h" #include "tables.h" #include "text.h" #include "types.h" #include "util.h" -static Table_t function_names = {}; +typedef struct { + Text_t filename, name; + int64_t line_num; +} func_info_t; -public void register_function(void *fn, Text_t name) +static NamedType_t fields[] = { + {.name="filename", .type=&Text$info}, + {.name="name", .type=&Text$info}, + {.name="line_num", .type=&Int64$info}, +}; + +static const TypeInfo_t func_info_type = {.size=sizeof(func_info_t), .align=__alignof__(func_info_t), .metamethods=Struct$metamethods, + .tag=StructInfo, .StructInfo.name="FuncInfo", + .StructInfo.num_fields=3, .StructInfo.fields=fields}; +static Table_t function_info = {}; + +public void register_function(void *fn, Text_t filename, int64_t line_num, Text_t name) { - Table$set(&function_names, &fn, &name, Table$info(Function$info("???"), &Text$info)); + func_info_t info = { + .filename=filename, + .line_num=line_num, + .name=name, + }; + Table$set(&function_info, &fn, &info, Table$info(Function$info("???"), &func_info_type)); } -PUREFUNC public Text_t *get_function_name(void *fn) +PUREFUNC static func_info_t *get_function_info(void *fn) { - return Table$get(function_names, &fn, Table$info(Function$info("???"), &Text$info)); + func_info_t *info = Table$get(function_info, &fn, Table$info(Function$info("???"), &func_info_type)); + if (info) return info; + + void *closest_fn = NULL; + for (int64_t i = 0; i < function_info.entries.length; i++) { + struct { void *fn; func_info_t info; } *entry = function_info.entries.data + i*function_info.entries.stride; + if (entry->fn > fn || entry->fn < closest_fn) continue; + closest_fn = entry->fn; + info = &entry->info; + } + return info; +} + +PUREFUNC public Text_t get_function_name(void *fn) +{ + func_info_t *info = get_function_info(fn); + return info ? info->name : NONE_TEXT; +} + +PUREFUNC public Text_t get_function_filename(void *fn) +{ + func_info_t *info = get_function_info(fn); + return info ? info->filename : NONE_TEXT; +} + +PUREFUNC public int64_t get_function_line_num(void *fn) +{ + func_info_t *info = get_function_info(fn); + return info ? info->line_num : -1; } public Text_t Func$as_text(const void *fn, bool colorize, const TypeInfo_t *type) @@ -26,9 +75,14 @@ public Text_t Func$as_text(const void *fn, bool colorize, const TypeInfo_t *type (void)fn; Text_t text = Text$from_str(type->FunctionInfo.type_str); if (fn) { - Text_t *name = get_function_name(*(void**)fn); - if (name) - text = *name; + OptionalText_t name = get_function_name(*(void**)fn); + if (name.length >= 0) + text = name; + + OptionalText_t filename = get_function_filename(*(void**)fn); + int64_t line_num = get_function_line_num(*(void**)fn); + if (filename.length >= 0) + text = Text$format("%k [%k:%ld]", &text, &filename, line_num); } if (fn && colorize) text = Text$concat(Text("\x1b[32;1m"), text, Text("\x1b[m")); diff --git a/stdlib/functiontype.h b/stdlib/functiontype.h index 4dfef3b..9252f5f 100644 --- a/stdlib/functiontype.h +++ b/stdlib/functiontype.h @@ -1,15 +1,19 @@ #pragma once #include +#include #include "metamethods.h" +#include "optionals.h" #include "types.h" #include "util.h" // Logic for handling function type values -void register_function(void *fn, Text_t name); -Text_t *get_function_name(void *fn); +void register_function(void *fn, Text_t filename, int64_t line_num, Text_t name); +OptionalText_t get_function_name(void *fn); +OptionalText_t get_function_filename(void *fn); +int64_t get_function_line_num(void *fn); Text_t Func$as_text(const void *fn, bool colorize, const TypeInfo_t *type); PUREFUNC bool Func$is_none(const void *obj, const TypeInfo_t*); diff --git a/stdlib/stdlib.c b/stdlib/stdlib.c index 2110213..5427599 100644 --- a/stdlib/stdlib.c +++ b/stdlib/stdlib.c @@ -13,6 +13,7 @@ #include "bools.h" #include "files.h" +#include "functiontype.h" #include "integers.h" #include "optionals.h" #include "metamethods.h"