From ed8b8901c067f0d378f973622f5f6d560d21e914 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Tue, 24 Sep 2024 14:54:22 -0400 Subject: [PATCH] Add '$' prefix on all user code --- compile.c | 84 ++++++++++++++++++++++++++++------------------ enums.c | 14 ++++---- environment.c | 12 ++++--- environment.h | 6 ++-- stdlib/optionals.c | 2 +- stdlib/ranges.c | 2 +- stdlib/ranges.h | 2 +- stdlib/threads.c | 17 +++++----- stdlib/threads.h | 14 ++++---- structs.c | 14 ++++---- tomo.c | 9 +++-- typecheck.c | 19 +++++------ 12 files changed, 108 insertions(+), 87 deletions(-) diff --git a/compile.c b/compile.c index ccc6412..17fe201 100644 --- a/compile.c +++ b/compile.c @@ -200,6 +200,9 @@ CORD compile_declaration(type_t *t, CORD name) CORD compile_type(type_t *t) { + if (t == THREAD_TYPE) return "Thread_t"; + else if (t == RANGE_TYPE) return "Range_t"; + switch (t->tag) { case ReturnType: errx(1, "Shouldn't be compiling ReturnType to a type"); case AbortType: return "void"; @@ -213,7 +216,16 @@ CORD compile_type(type_t *t) case NumType: return Match(t, NumType)->bits == TYPE_NBITS64 ? "Num_t" : CORD_asprintf("Num%ld_t", Match(t, NumType)->bits); case TextType: { auto text = Match(t, TextType); - return text->lang ? CORD_all(namespace_prefix(text->env->libname, text->env->namespace->parent), text->lang, "_t") : "Text_t"; + if (!text->lang || streq(text->lang, "Text")) + return "Text_t"; + else if (streq(text->lang, "Pattern")) + return "Pattern_t"; + else if (streq(text->lang, "Path")) + return "Path_t"; + else if (streq(text->lang, "Shell")) + return "Shell_t"; + else + return CORD_all(namespace_prefix(text->env, text->env->namespace->parent), text->lang, "_t"); } case ArrayType: return "Array_t"; case SetType: return "Table_t"; @@ -231,14 +243,12 @@ CORD compile_type(type_t *t) case ClosureType: return "Closure_t"; case PointerType: return CORD_cat(compile_type(Match(t, PointerType)->pointed), "*"); case StructType: { - if (t == THREAD_TYPE) - return "pthread_t*"; auto s = Match(t, StructType); - return CORD_all("struct ", namespace_prefix(s->env->libname, s->env->namespace->parent), s->name, "_s"); + return CORD_all("struct ", namespace_prefix(s->env, s->env->namespace->parent), s->name, "_s"); } case EnumType: { auto e = Match(t, EnumType); - return CORD_all(namespace_prefix(e->env->libname, e->env->namespace->parent), e->name, "_t"); + return CORD_all(namespace_prefix(e->env, e->env->namespace->parent), e->name, "_t"); } case OptionalType: { type_t *nonnull = Match(t, OptionalType)->type; @@ -253,9 +263,9 @@ CORD compile_type(type_t *t) return CORD_all("Optional", compile_type(nonnull)); case StructType: { if (nonnull == THREAD_TYPE) - return "pthread_t*"; + return "Thread_t"; auto s = Match(nonnull, StructType); - return CORD_all(namespace_prefix(s->env->libname, s->env->namespace->parent), "$Optional", s->name, "_t"); + return CORD_all(namespace_prefix(s->env, s->env->namespace->parent), "$Optional", s->name, "_t"); } default: compiler_err(NULL, NULL, NULL, "Optional types are not supported for: %T", t); @@ -395,7 +405,7 @@ CORD compile_statement(env_t *env, ast_t *ast) "switch (subject.tag) {"); for (when_clause_t *clause = when->clauses; clause; clause = clause->next) { const char *clause_tag_name = Match(clause->tag_name, Var)->name; - code = CORD_all(code, "case ", namespace_prefix(enum_t->env->libname, enum_t->env->namespace), "tag$", clause_tag_name, ": {\n"); + code = CORD_all(code, "case ", namespace_prefix(enum_t->env, enum_t->env->namespace), "tag$", clause_tag_name, ": {\n"); type_t *tag_type = NULL; for (tag_t *tag = enum_t->tags; tag; tag = tag->next) { if (streq(tag->name, clause_tag_name)) { @@ -739,7 +749,7 @@ CORD compile_statement(env_t *env, ast_t *ast) case LangDef: { auto def = Match(ast, LangDef); CORD_appendf(&env->code->typeinfos, "public const TypeInfo %r%s = {%zu, %zu, {.tag=TextInfo, .TextInfo={%r}}};\n", - namespace_prefix(env->libname, env->namespace), def->name, sizeof(Text_t), __alignof__(Text_t), + namespace_prefix(env, env->namespace), def->name, sizeof(Text_t), __alignof__(Text_t), CORD_quoted(def->name)); compile_namespace(env, def->name, def->namespace); return CORD_EMPTY; @@ -796,7 +806,7 @@ CORD compile_statement(env_t *env, ast_t *ast) CORD body = compile_statement(body_scope, fndef->body); if (streq(Match(fndef->name, Var)->name, "main")) - body = CORD_all(env->namespace->name, "$$initialize();\n", body); + body = CORD_all("$", env->namespace->name, "$$initialize();\n", body); if (CORD_fetch(body, 0) != '{') body = CORD_asprintf("{\n%r\n}", body); env->code->funcs = CORD_all(env->code->funcs, code, " ", body, "\n"); @@ -1370,7 +1380,7 @@ CORD compile_statement(env_t *env, ast_t *ast) auto use = Match(ast, Use); if (use->what == USE_LOCAL) { CORD name = file_base_name(Match(ast, Use)->path); - env->code->variable_initializers = CORD_all(env->code->variable_initializers, name, "$$initialize();\n"); + env->code->variable_initializers = CORD_all(env->code->variable_initializers, "$", name, "$$initialize();\n"); } else if (use->what == USE_C_CODE) { return CORD_all("#include \"", use->path, "\"\n"); } else if (use->what == USE_MODULE) { @@ -1383,7 +1393,7 @@ CORD compile_statement(env_t *env, ast_t *ast) for (size_t i = 0; i < tm_files.gl_pathc; i++) { const char *filename = tm_files.gl_pathv[i]; env->code->variable_initializers = CORD_all( - env->code->variable_initializers, lib_id, "$", file_base_name(filename), "$$initialize();\n"); + env->code->variable_initializers, "$", lib_id, "$", file_base_name(filename), "$$initialize();\n"); } globfree(&tm_files); } @@ -1783,7 +1793,7 @@ CORD compile_null(type_t *t) case StructType: return CORD_all("((", compile_type(Type(OptionalType, .type=t)), "){.is_null=true})"); case EnumType: { env_t *enum_env = Match(t, EnumType)->env; - return CORD_all("((", compile_type(t), "){", namespace_prefix(enum_env->libname, enum_env->namespace), "null})"); + return CORD_all("((", compile_type(t), "){", namespace_prefix(enum_env, enum_env->namespace), "null})"); } default: compiler_err(NULL, NULL, NULL, "Null isn't implemented for this type: %T", t); } @@ -2146,8 +2156,13 @@ CORD compile(env_t *env, ast_t *ast) if (!text_t || text_t->tag != TextType) code_err(ast, "%s is not a valid text language name", lang); - CORD lang_constructor = !lang ? "Text" - : CORD_all(namespace_prefix(Match(text_t, TextType)->env->libname, Match(text_t, TextType)->env->namespace->parent), lang); + CORD lang_constructor; + if (!lang || streq(lang, "Text")) + lang_constructor = "Text"; + else if (streq(lang, "Pattern") || streq(lang, "Path") || streq(lang, "Shell")) + lang_constructor = lang; + else + lang_constructor = CORD_all(namespace_prefix(Match(text_t, TextType)->env, Match(text_t, TextType)->env->namespace->parent), lang); ast_list_t *chunks = Match(ast, TextJoin)->children; if (!chunks) { @@ -2441,7 +2456,7 @@ CORD compile(env_t *env, ast_t *ast) } case Lambda: { auto lambda = Match(ast, Lambda); - CORD name = CORD_asprintf("%rlambda$%ld", namespace_prefix(env->libname, env->namespace), lambda->id); + CORD name = CORD_asprintf("%rlambda$%ld", namespace_prefix(env, env->namespace), lambda->id); env->code->function_naming = CORD_all( env->code->function_naming, @@ -3158,7 +3173,7 @@ CORD compile(env_t *env, ast_t *ast) auto e = Match(value_t, EnumType); for (tag_t *tag = e->tags; tag; tag = tag->next) { if (streq(f->field, tag->name)) { - CORD prefix = namespace_prefix(e->env->libname, e->env->namespace); + CORD prefix = namespace_prefix(e->env, e->env->namespace); if (fielded_t->tag == PointerType) { CORD fielded = compile_to_pointer_depth(env, f->fielded, 1, false); return CORD_all("((", fielded, ")->tag == ", prefix, "tag$", tag->name, ")"); @@ -3275,7 +3290,7 @@ CORD compile(env_t *env, ast_t *ast) void compile_namespace(env_t *env, const char *ns_name, ast_t *block) { env_t *ns_env = namespace_env(env, ns_name); - CORD prefix = namespace_prefix(ns_env->libname, ns_env->namespace); + CORD prefix = namespace_prefix(ns_env, ns_env->namespace); // First prepare variable initializers to prevent unitialized access: for (ast_list_t *stmt = block ? Match(block, Block)->statements : NULL; stmt; stmt = stmt->next) { @@ -3357,6 +3372,9 @@ CORD compile_namespace_header(env_t *env, const char *ns_name, ast_t *block) CORD compile_type_info(env_t *env, type_t *t) { + if (t == THREAD_TYPE) return "&Thread$info"; + else if (t == RANGE_TYPE) return "&Range$info"; + switch (t->tag) { case BoolType: case ByteType: case IntType: case BigIntType: case NumType: case CStringType: return CORD_all("&", type_to_cord(t), "$info"); @@ -3370,15 +3388,15 @@ CORD compile_type_info(env_t *env, type_t *t) return "&Shell$info"; else if (streq(text->lang, "Path")) return "&Path$info"; - return CORD_all("(&", namespace_prefix(text->env->libname, text->env->namespace->parent), text->lang, ")"); + return CORD_all("(&", namespace_prefix(text->env, text->env->namespace->parent), text->lang, ")"); } case StructType: { auto s = Match(t, StructType); - return CORD_all("(&", namespace_prefix(s->env->libname, s->env->namespace->parent), s->name, ")"); + return CORD_all("(&", namespace_prefix(s->env, s->env->namespace->parent), s->name, ")"); } case EnumType: { auto e = Match(t, EnumType); - return CORD_all("(&", namespace_prefix(e->env->libname, e->env->namespace->parent), e->name, ")"); + return CORD_all("(&", namespace_prefix(e->env, e->env->namespace->parent), e->name, ")"); } case ArrayType: { type_t *item_t = Match(t, ArrayType)->item_type; @@ -3706,7 +3724,7 @@ CORD compile_file(env_t *env, ast_t *ast) if (stmt->ast->tag == Declare) { auto decl = Match(stmt->ast, Declare); const char *decl_name = Match(decl->var, Var)->name; - CORD full_name = CORD_all(namespace_prefix(env->libname, env->namespace), decl_name); + CORD full_name = CORD_all(namespace_prefix(env, env->namespace), decl_name); type_t *t = get_type(env, decl->value); if (t->tag == AbortType || t->tag == VoidType || t->tag == ReturnType) code_err(stmt->ast, "You can't declare a variable with a %T value", t); @@ -3732,7 +3750,7 @@ CORD compile_file(env_t *env, ast_t *ast) if (stmt->ast->tag == Declare) { auto decl = Match(stmt->ast, Declare); const char *decl_name = Match(decl->var, Var)->name; - CORD full_name = CORD_all(namespace_prefix(env->libname, env->namespace), decl_name); + CORD full_name = CORD_all(namespace_prefix(env, env->namespace), decl_name); bool is_private = (decl_name[0] == '_'); type_t *t = get_type(env, decl->value); if (decl->value->tag == Use) { @@ -3777,7 +3795,7 @@ CORD compile_file(env_t *env, ast_t *ast) env->code->staticdefs, "\n", env->code->funcs, "\n", env->code->typeinfos, "\n", - "public void ", env->namespace->name, "$$initialize(void) {\n", + "public void $", env->namespace->name, "$$initialize(void) {\n", "static bool initialized = false;\n", "if (initialized) return;\n", "initialized = true;\n", @@ -3808,7 +3826,7 @@ CORD compile_statement_header(env_t *env, ast_t *ast) return CORD_all( compile_statement_header(env, decl->value), - "extern ", compile_declaration(t, CORD_cat(namespace_prefix(env->libname, env->namespace), decl_name)), ";\n"); + "extern ", compile_declaration(t, CORD_cat(namespace_prefix(env, env->namespace), decl_name)), ";\n"); } case Use: { auto use = Match(ast, Use); @@ -3835,14 +3853,14 @@ CORD compile_statement_header(env_t *env, ast_t *ast) } case LangDef: { auto def = Match(ast, LangDef); - CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name); + CORD full_name = CORD_cat(namespace_prefix(env, env->namespace), def->name); return CORD_all( - "typedef Text_t ", namespace_prefix(env->libname, env->namespace), def->name, "_t;\n" + "typedef Text_t ", namespace_prefix(env, env->namespace), def->name, "_t;\n" // Constructor macro: - "#define ", namespace_prefix(env->libname, env->namespace), def->name, - "(text) ((", namespace_prefix(env->libname, env->namespace), def->name, "_t){.length=sizeof(text)-1, .tag=TEXT_ASCII, .ascii=\"\" text})\n" - "#define ", namespace_prefix(env->libname, env->namespace), def->name, - "s(...) ((", namespace_prefix(env->libname, env->namespace), def->name, "_t)Texts(__VA_ARGS__))\n" + "#define ", namespace_prefix(env, env->namespace), def->name, + "(text) ((", namespace_prefix(env, env->namespace), def->name, "_t){.length=sizeof(text)-1, .tag=TEXT_ASCII, .ascii=\"\" text})\n" + "#define ", namespace_prefix(env, env->namespace), def->name, + "s(...) ((", namespace_prefix(env, env->namespace), def->name, "_t)Texts(__VA_ARGS__))\n" "extern const TypeInfo ", full_name, ";\n", compile_namespace_header(env, def->name, def->namespace) ); @@ -3862,7 +3880,7 @@ CORD compile_statement_header(env_t *env, ast_t *ast) type_t *ret_t = fndef->ret_type ? parse_type_ast(env, fndef->ret_type) : Type(VoidType); CORD ret_type_code = compile_type(ret_t); - return CORD_all(ret_type_code, " ", namespace_prefix(env->libname, env->namespace), decl_name, arg_signature, ";\n"); + return CORD_all(ret_type_code, " ", namespace_prefix(env, env->namespace), decl_name, arg_signature, ";\n"); } case Extern: { auto ext = Match(ast, Extern); @@ -3907,7 +3925,7 @@ CORD compile_file_header(env_t *env, ast_t *ast) compile_typedef_info_t info = {.env=env, .header=&header}; visit_topologically(Match(ast, Block)->statements, (Closure_t){.fn=(void*)_visit_statement, &info}); - header = CORD_all(header, "void ", env->namespace->name, "$$initialize(void);\n"); + header = CORD_all(header, "void $", env->namespace->name, "$$initialize(void);\n"); return header; } diff --git a/enums.c b/enums.c index ab99378..558065f 100644 --- a/enums.c +++ b/enums.c @@ -24,7 +24,7 @@ PUREFUNC static bool has_extra_data(tag_ast_t *tags) static CORD compile_str_method(env_t *env, ast_t *ast) { auto def = Match(ast, EnumDef); - CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name); + CORD full_name = CORD_cat(namespace_prefix(env, env->namespace), def->name); CORD str_func = CORD_all("static Text_t ", full_name, "$as_text(", full_name, "_t *obj, bool use_color) {\n" "\tif (!obj) return Text(\"", def->name, "\");\n" "switch (obj->tag) {\n"); @@ -64,7 +64,7 @@ static CORD compile_str_method(env_t *env, ast_t *ast) static CORD compile_compare_method(env_t *env, ast_t *ast) { auto def = Match(ast, EnumDef); - CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name); + CORD full_name = CORD_cat(namespace_prefix(env, env->namespace), def->name); if (!has_extra_data(def->tags)) { // Comparisons are simpler if there is only a tag, no tagged data: return CORD_all("static int ", full_name, "$compare(const ", full_name, "_t *x, const ", full_name, @@ -95,7 +95,7 @@ static CORD compile_compare_method(env_t *env, ast_t *ast) static CORD compile_equals_method(env_t *env, ast_t *ast) { auto def = Match(ast, EnumDef); - CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name); + CORD full_name = CORD_cat(namespace_prefix(env, env->namespace), def->name); if (!has_extra_data(def->tags)) { // Equality is simpler if there is only a tag, no tagged data: return CORD_all("static bool ", full_name, "$equal(const ", full_name, "_t *x, const ", full_name, @@ -125,7 +125,7 @@ static CORD compile_equals_method(env_t *env, ast_t *ast) static CORD compile_hash_method(env_t *env, ast_t *ast) { auto def = Match(ast, EnumDef); - CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name); + CORD full_name = CORD_cat(namespace_prefix(env, env->namespace), def->name); if (!has_extra_data(def->tags)) { // Hashing is simpler if there is only a tag, no tagged data: return CORD_all("static uint64_t ", full_name, "$hash(const ", full_name, "_t *obj, const TypeInfo *info) {\n" @@ -155,7 +155,7 @@ static CORD compile_hash_method(env_t *env, ast_t *ast) void compile_enum_def(env_t *env, ast_t *ast) { auto def = Match(ast, EnumDef); - CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name); + CORD full_name = CORD_cat(namespace_prefix(env, env->namespace), def->name); for (tag_ast_t *tag = def->tags; tag; tag = tag->next) { compile_struct_def(env, WrapAST(ast, StructDef, .name=CORD_to_const_char_star(CORD_all(def->name, "$", tag->name)), .fields=tag->fields)); if (tag->fields) { // Constructor macros: @@ -206,7 +206,7 @@ void compile_enum_def(env_t *env, ast_t *ast) CORD compile_enum_header(env_t *env, ast_t *ast) { auto def = Match(ast, EnumDef); - CORD full_name = CORD_all(namespace_prefix(env->libname, env->namespace), def->name); + CORD full_name = CORD_all(namespace_prefix(env, env->namespace), def->name); CORD all_defs = CORD_all("typedef struct ", full_name, "_s ", full_name, "_t;\n"); CORD enum_def = CORD_all("struct ", full_name, "_s {\n" "\tenum { ", full_name, "$null=0, "); @@ -228,7 +228,7 @@ CORD compile_enum_header(env_t *env, ast_t *ast) all_defs = CORD_all(all_defs, "extern const TypeInfo ", full_name, ";\n"); for (tag_ast_t *tag = def->tags; tag; tag = tag->next) { all_defs = CORD_all(all_defs, - "extern const TypeInfo ", namespace_prefix(env->libname, env->namespace), def->name, "$", tag->name, ";\n"); + "extern const TypeInfo ", namespace_prefix(env, env->namespace), def->name, "$", tag->name, ";\n"); if (tag->fields) { // Constructor macros: CORD arg_sig = CORD_EMPTY; for (arg_ast_t *field = tag->fields; field; field = field->next) { diff --git a/environment.c b/environment.c index 0232781..050fac2 100644 --- a/environment.c +++ b/environment.c @@ -15,7 +15,7 @@ type_t *TEXT_TYPE = NULL; type_t *RANGE_TYPE = NULL; public type_t *THREAD_TYPE = NULL; -env_t *new_compilation_unit(CORD *libname) +env_t *new_compilation_unit(CORD libname) { env_t *env = new(env_t); env->code = new(compilation_unit_t); @@ -338,7 +338,7 @@ env_t *new_compilation_unit(CORD *libname) {"utf32_codepoints", "Text$utf32_codepoints", "func(text:Text)->[Int32]"}, {"utf8_bytes", "Text$utf8_bytes", "func(text:Text)->[Byte]"}, )}, - {"Thread", THREAD_TYPE, "pthread_t*", "Thread", TypedArray(ns_entry_t, + {"Thread", THREAD_TYPE, "Thread_t", "Thread", TypedArray(ns_entry_t, {"new", "Thread$new", "func(fn:func())->Thread"}, {"cancel", "Thread$cancel", "func(thread:Thread)"}, {"join", "Thread$join", "func(thread:Thread)"}, @@ -402,13 +402,15 @@ env_t *new_compilation_unit(CORD *libname) return lib_env; } -CORD namespace_prefix(CORD *libname, namespace_t *ns) +CORD namespace_prefix(env_t *env, namespace_t *ns) { CORD prefix = CORD_EMPTY; for (; ns; ns = ns->parent) prefix = CORD_all(ns->name, "$", prefix); - if (libname && *libname) - prefix = CORD_all(*libname, "$", prefix); + if (env->libname) + prefix = CORD_all("$", env->libname, "$", prefix); + else + prefix = CORD_all("$", prefix); return prefix; } diff --git a/environment.h b/environment.h index e5f1753..2fc0771 100644 --- a/environment.h +++ b/environment.h @@ -52,7 +52,7 @@ typedef struct env_s { fn_ctx_t *fn_ctx; loop_ctx_t *loop_ctx; deferral_t *deferred; - CORD *libname; // Pointer to currently compiling library name (if any) + CORD libname; // Currently compiling library name (if any) namespace_t *namespace; Closure_t *comprehension_action; } env_t; @@ -65,9 +65,9 @@ typedef struct { }; } binding_t; -env_t *new_compilation_unit(CORD *libname); +env_t *new_compilation_unit(CORD libname); env_t *load_module_env(env_t *env, ast_t *ast); -CORD namespace_prefix(CORD *libname, namespace_t *ns); +CORD namespace_prefix(env_t *env, namespace_t *ns); env_t *namespace_scope(env_t *env); env_t *fresh_scope(env_t *env); env_t *for_scope(env_t *env, ast_t *ast); diff --git a/stdlib/optionals.c b/stdlib/optionals.c index e21be50..1dc770a 100644 --- a/stdlib/optionals.c +++ b/stdlib/optionals.c @@ -36,7 +36,7 @@ public PUREFUNC bool is_null(const void *obj, const TypeInfo *non_optional_type) return ((OptionalInt8_t*)obj)->is_null; else if (non_optional_type == &Byte$info) return ((OptionalByte_t*)obj)->is_null; - else if (non_optional_type == &Thread) + else if (non_optional_type == &Thread$info) return *(pthread_t**)obj == NULL; switch (non_optional_type->tag) { diff --git a/stdlib/ranges.c b/stdlib/ranges.c index 9dfd1ef..6c81c15 100644 --- a/stdlib/ranges.c +++ b/stdlib/ranges.c @@ -54,7 +54,7 @@ PUREFUNC public Range_t Range$by(Range_t r, Int_t step) return (Range_t){r.first, r.last, Int$times(step, r.step)}; } -public const TypeInfo Range = {sizeof(Range_t), __alignof(Range_t), {.tag=CustomInfo, .CustomInfo={ +public const TypeInfo Range$info = {sizeof(Range_t), __alignof(Range_t), {.tag=CustomInfo, .CustomInfo={ .as_text=(void*)Range$as_text, .compare=(void*)Range$compare, .equal=(void*)Range$equal, diff --git a/stdlib/ranges.h b/stdlib/ranges.h index 2a4f1d6..933b9ae 100644 --- a/stdlib/ranges.h +++ b/stdlib/ranges.h @@ -5,6 +5,6 @@ PUREFUNC Range_t Range$reversed(Range_t r); PUREFUNC Range_t Range$by(Range_t r, Int_t step); -extern const TypeInfo Range; +extern const TypeInfo Range$info; // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1 diff --git a/stdlib/threads.c b/stdlib/threads.c index 74e7383..59e98dd 100644 --- a/stdlib/threads.c +++ b/stdlib/threads.c @@ -12,32 +12,33 @@ #include "arrays.h" #include "text.h" +#include "threads.h" #include "types.h" #include "util.h" -public pthread_t *Thread$new(Closure_t fn) +public Thread_t Thread$new(Closure_t fn) { - pthread_t *thread = new(pthread_t); + Thread_t thread = new(pthread_t); pthread_create(thread, NULL, fn.fn, fn.userdata); return thread; } -public void Thread$join(pthread_t *thread) +public void Thread$join(Thread_t thread) { pthread_join(*thread, NULL); } -public void Thread$cancel(pthread_t *thread) +public void Thread$cancel(Thread_t thread) { pthread_cancel(*thread); } -public void Thread$detach(pthread_t *thread) +public void Thread$detach(Thread_t thread) { pthread_detach(*thread); } -Text_t Thread$as_text(const pthread_t **thread, bool colorize, const TypeInfo *type) +Text_t Thread$as_text(const Thread_t *thread, bool colorize, const TypeInfo *type) { (void)type; if (!thread) { @@ -46,8 +47,8 @@ Text_t Thread$as_text(const pthread_t **thread, bool colorize, const TypeInfo *t return Text$format(colorize ? "\x1b[34;1mThread(%p)\x1b[m" : "Thread(%p)", *thread); } -public const TypeInfo Thread = { - .size=sizeof(pthread_t*), .align=__alignof(pthread_t*), +public const TypeInfo Thread$info = { + .size=sizeof(Thread_t), .align=__alignof(Thread_t), .tag=CustomInfo, .CustomInfo={.as_text=(void*)Thread$as_text}, }; diff --git a/stdlib/threads.h b/stdlib/threads.h index 5209167..f46840b 100644 --- a/stdlib/threads.h +++ b/stdlib/threads.h @@ -9,12 +9,14 @@ #include "types.h" #include "util.h" -pthread_t *Thread$new(Closure_t fn); -void Thread$cancel(pthread_t *thread); -void Thread$join(pthread_t *thread); -void Thread$detach(pthread_t *thread); -Text_t Thread$as_text(const pthread_t **thread, bool colorize, const TypeInfo *type); +#define Thread_t pthread_t* -extern TypeInfo Thread; +Thread_t Thread$new(Closure_t fn); +void Thread$cancel(Thread_t thread); +void Thread$join(Thread_t thread); +void Thread$detach(Thread_t thread); +Text_t Thread$as_text(const Thread_t *thread, bool colorize, const TypeInfo *type); + +extern const TypeInfo Thread$info; // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/structs.c b/structs.c index 48fce6d..1c29421 100644 --- a/structs.c +++ b/structs.c @@ -15,7 +15,7 @@ static CORD compile_str_method(env_t *env, ast_t *ast) { auto def = Match(ast, StructDef); - CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name); + CORD full_name = CORD_cat(namespace_prefix(env, env->namespace), def->name); const char *name = def->name; const char *dollar = strrchr(name, '$'); if (dollar) name = dollar + 1; @@ -45,7 +45,7 @@ static CORD compile_str_method(env_t *env, ast_t *ast) static CORD compile_compare_method(env_t *env, ast_t *ast) { auto def = Match(ast, StructDef); - CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name); + CORD full_name = CORD_cat(namespace_prefix(env, env->namespace), def->name); CORD cmp_func = CORD_all("static int ", full_name, "$compare(const ", full_name, "_t *x, const ", full_name, "_t *y, const TypeInfo *info) {\n" "(void)info;\n", @@ -73,7 +73,7 @@ static CORD compile_compare_method(env_t *env, ast_t *ast) static CORD compile_equals_method(env_t *env, ast_t *ast) { auto def = Match(ast, StructDef); - CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name); + CORD full_name = CORD_cat(namespace_prefix(env, env->namespace), def->name); CORD eq_func = CORD_all("static bool ", full_name, "$equal(const ", full_name, "_t *x, const ", full_name, "_t *y, const TypeInfo *info) {\n" "(void)info;\n"); @@ -102,7 +102,7 @@ static CORD compile_equals_method(env_t *env, ast_t *ast) static CORD compile_hash_method(env_t *env, ast_t *ast) { auto def = Match(ast, StructDef); - CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name); + CORD full_name = CORD_cat(namespace_prefix(env, env->namespace), def->name); CORD hash_func = CORD_all("static uint64_t ", full_name, "$hash(const ", full_name, "_t *obj, const TypeInfo *info) {\n" "(void)info;\n" "uint64_t field_hashes[] = {"); @@ -121,7 +121,7 @@ static CORD compile_hash_method(env_t *env, ast_t *ast) void compile_struct_def(env_t *env, ast_t *ast) { auto def = Match(ast, StructDef); - CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name); + CORD full_name = CORD_cat(namespace_prefix(env, env->namespace), def->name); type_t *t = Table$str_get(*env->types, def->name); assert(t && t->tag == StructType); @@ -174,7 +174,7 @@ void compile_struct_def(env_t *env, ast_t *ast) CORD compile_struct_header(env_t *env, ast_t *ast) { auto def = Match(ast, StructDef); - CORD full_name = CORD_cat(namespace_prefix(env->libname, env->namespace), def->name); + CORD full_name = CORD_cat(namespace_prefix(env, env->namespace), def->name); CORD fields = CORD_EMPTY; for (arg_ast_t *field = def->fields; field; field = field->next) { @@ -192,7 +192,7 @@ CORD compile_struct_header(env_t *env, ast_t *ast) "typedef struct {\n", full_name, "_t value;\n" "Bool_t is_null:1;\n" - "} ", namespace_prefix(env->libname, env->namespace), "$Optional", def->name, "_t;\n" + "} ", namespace_prefix(env, env->namespace), "$Optional", def->name, "_t;\n" "extern const TypeInfo ", full_name, ";\n", compile_namespace_header(env, def->name, def->namespace)); } diff --git a/tomo.c b/tomo.c index e39e14a..4f26f66 100644 --- a/tomo.c +++ b/tomo.c @@ -232,7 +232,7 @@ static void _compile_file_header_for_library(env_t *env, const char *filename, T visit_topologically( Match(file_ast, Block)->statements, (Closure_t){.fn=(void*)_compile_statement_header_for_library, &info}); - CORD_fprintf(output, "void %r$initialize(void);\n", namespace_prefix(module_env->libname, module_env->namespace)); + CORD_fprintf(output, "void %r$initialize(void);\n", namespace_prefix(module_env, module_env->namespace)); } void build_library(const char *lib_dir_name) @@ -247,8 +247,7 @@ void build_library(const char *lib_dir_name) // Library name replaces all stretchs of non-alphanumeric chars with an underscore // So e.g. https://github.com/foo/baz --> https_github_com_foo_baz - const char *lib_id = escape_lib_name(lib_dir_name); - env->libname = &lib_id; + env->libname = escape_lib_name(lib_dir_name); // Build a "whatever.h" header that loads all the headers: FILE *header_prog = CORD_RUN(autofmt ? autofmt : "cat", " 2>/dev/null >'", lib_dir_name, ".h'"); @@ -269,7 +268,7 @@ void build_library(const char *lib_dir_name) FILE *prog; for (size_t i = 0; i < tm_files.gl_pathc; i++) { const char *filename = tm_files.gl_pathv[i]; - prog = CORD_RUN("nm -Ug -fjust-symbols ", filename, ".o | sed 's/.*/\\0 ", lib_id, "$\\0/' >>symbol_renames.txt"); + prog = CORD_RUN("nm -Ug -fjust-symbols ", filename, ".o | sed 's/.*/\\0 $", env->libname, "\\0/' >>symbol_renames.txt"); int status = pclose(prog); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) errx(WEXITSTATUS(status), "Failed to create symbol rename table with `nm` and `sed`"); @@ -523,7 +522,7 @@ void transpile_code(env_t *base_env, const char *filename, bool force_retranspil CORD_put(CORD_all( "int ", main_binding->code, "$parse_and_run(int argc, char *argv[]) {\n" "tomo_init();\n", - module_env->namespace->name, "$$initialize();\n" + "$", module_env->namespace->name, "$$initialize();\n" "\n", compile_cli_arg_call(module_env, main_binding->code, main_binding->type), "return 0;\n" diff --git a/typecheck.c b/typecheck.c index afeac42..f993604 100644 --- a/typecheck.c +++ b/typecheck.c @@ -161,8 +161,7 @@ static env_t *load_module(env_t *env, ast_t *module_ast) Table$str_set(env->imports, use->path, module_env); char *libname_id = Text$as_c_string( Text$replace(Text$from_str(use->path), Pattern("{1+ !alphanumeric}"), Text("_"), Pattern(""), false)); - module_env->libname = new(CORD); - *module_env->libname = (CORD)libname_id; + module_env->libname = libname_id; for (size_t i = 0; i < tm_files.gl_pathc; i++) { const char *filename = tm_files.gl_pathv[i]; ast_t *ast = parse_file(filename, NULL); @@ -205,7 +204,7 @@ void prebind_statement(env_t *env, ast_t *statement) type_t *type = Type(StructType, .name=def->name, .opaque=true, .env=ns_env); // placeholder Table$str_set(env->types, def->name, type); set_binding(env, def->name, new(binding_t, .type=Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env), - .code=CORD_all(namespace_prefix(env->libname, env->namespace), def->name))); + .code=CORD_all(namespace_prefix(env, env->namespace), def->name))); for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) prebind_statement(ns_env, stmt->ast); break; @@ -219,7 +218,7 @@ void prebind_statement(env_t *env, ast_t *statement) type_t *type = Type(EnumType, .name=def->name, .opaque=true, .env=ns_env); // placeholder Table$str_set(env->types, def->name, type); set_binding(env, def->name, new(binding_t, .type=Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env), - .code=CORD_all(namespace_prefix(env->libname, env->namespace), def->name))); + .code=CORD_all(namespace_prefix(env, env->namespace), def->name))); for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) prebind_statement(ns_env, stmt->ast); break; @@ -233,7 +232,7 @@ void prebind_statement(env_t *env, ast_t *statement) type_t *type = Type(TextType, .lang=def->name, .env=ns_env); Table$str_set(env->types, def->name, type); set_binding(env, def->name, new(binding_t, .type=Type(TypeInfoType, .name=def->name, .type=type, .env=ns_env), - .code=CORD_all(namespace_prefix(env->libname, env->namespace), def->name))); + .code=CORD_all(namespace_prefix(env, env->namespace), def->name))); for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) prebind_statement(ns_env, stmt->ast); break; @@ -266,7 +265,7 @@ void bind_statement(env_t *env, ast_t *statement) code_err(decl->value, "I couldn't figure out the type of this value"); if (type->tag == FunctionType) type = Type(ClosureType, type); - CORD prefix = namespace_prefix(env->libname, env->namespace); + CORD prefix = namespace_prefix(env, env->namespace); CORD code = CORD_cat(prefix ? prefix : "$", name); set_binding(env, name, new(binding_t, .type=type, .code=code)); break; @@ -277,7 +276,7 @@ void bind_statement(env_t *env, ast_t *statement) if (get_binding(env, name)) code_err(def->name, "A %T called '%s' has already been defined", get_binding(env, name)->type, name); type_t *type = get_function_def_type(env, statement); - CORD code = CORD_all(namespace_prefix(env->libname, env->namespace), name); + CORD code = CORD_all(namespace_prefix(env, env->namespace), name); set_binding(env, name, new(binding_t, .type=type, .code=code)); break; } @@ -346,9 +345,9 @@ void bind_statement(env_t *env, ast_t *statement) for (tag_t *tag = tags; tag; tag = tag->next) { if (Match(tag->type, StructType)->fields) { // Constructor: type_t *constructor_t = Type(FunctionType, .args=Match(tag->type, StructType)->fields, .ret=type); - set_binding(ns_env, tag->name, new(binding_t, .type=constructor_t, .code=CORD_all(namespace_prefix(env->libname, env->namespace), def->name, "$tagged$", tag->name))); + set_binding(ns_env, tag->name, new(binding_t, .type=constructor_t, .code=CORD_all(namespace_prefix(env, env->namespace), def->name, "$tagged$", tag->name))); } else { // Empty singleton value: - CORD code = CORD_all("(", namespace_prefix(env->libname, env->namespace), def->name, "_t){", namespace_prefix(env->libname, env->namespace), def->name, "$tag$", tag->name, "}"); + CORD code = CORD_all("(", namespace_prefix(env, env->namespace), def->name, "_t){", namespace_prefix(env, env->namespace), def->name, "$tag$", tag->name, "}"); set_binding(ns_env, tag->name, new(binding_t, .type=type, .code=code)); } Table$str_set(env->types, heap_strf("%s$%s", def->name, tag->name), tag->type); @@ -367,7 +366,7 @@ void bind_statement(env_t *env, ast_t *statement) set_binding(ns_env, "without_escaping", new(binding_t, .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE), .ret=type), - .code=CORD_all("(", namespace_prefix(env->libname, env->namespace), def->name, "_t)"))); + .code=CORD_all("(", namespace_prefix(env, env->namespace), def->name, "_t)"))); for (ast_list_t *stmt = def->namespace ? Match(def->namespace, Block)->statements : NULL; stmt; stmt = stmt->next) bind_statement(ns_env, stmt->ast);