Add '$' prefix on all user code
This commit is contained in:
parent
800e386105
commit
ed8b8901c0
84
compile.c
84
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;
|
||||
}
|
||||
|
||||
|
14
enums.c
14
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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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},
|
||||
};
|
||||
|
@ -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
|
||||
|
14
structs.c
14
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));
|
||||
}
|
||||
|
9
tomo.c
9
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"
|
||||
|
19
typecheck.c
19
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);
|
||||
|
Loading…
Reference in New Issue
Block a user