aboutsummaryrefslogtreecommitdiff
path: root/src/compile
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-10-02 23:57:30 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-10-02 23:57:30 -0400
commitbaea09062482674220a3686d488a283e6b9b8821 (patch)
tree33df470af1db2be53fabac50762c375951acb84e /src/compile
parent126050a6357d7ec1fd9901256de50923b6dd7c49 (diff)
parent597699243a6f935231ad83e63d22bf6ff9e4e547 (diff)
Merge branch 'zero-nones' into dev
Diffstat (limited to 'src/compile')
-rw-r--r--src/compile/cli.c8
-rw-r--r--src/compile/expressions.c12
-rw-r--r--src/compile/functions.c18
-rw-r--r--src/compile/lists.c4
-rw-r--r--src/compile/optionals.c27
-rw-r--r--src/compile/statements.c2
-rw-r--r--src/compile/tables.c4
7 files changed, 37 insertions, 38 deletions
diff --git a/src/compile/cli.c b/src/compile/cli.c
index b082239d..d93e5f56 100644
--- a/src/compile/cli.c
+++ b/src/compile/cli.c
@@ -60,19 +60,19 @@ Text_t compile_cli_arg_call(env_t *env, Text_t fn_name, type_t *fn_type, const c
type_t *t = get_arg_type(main_env, arg);
if (arg->default_val || arg->type->tag == OptionalType) {
OptionalText_t flag = flagify(arg->name, true);
- assert(flag.length >= 0);
+ assert(flag.tag != TEXT_NONE);
OptionalText_t alias_flag = flagify(arg->alias, true);
- Text_t flags = alias_flag.length >= 0 ? Texts(flag, "|", alias_flag) : flag;
+ Text_t flags = alias_flag.tag != TEXT_NONE ? Texts(flag, "|", alias_flag) : flag;
if (t->tag == BoolType || (t->tag == OptionalType && Match(t, OptionalType)->type->tag == BoolType))
usage = Texts(usage, "[", flags, "]");
else if (t->tag == ListType) usage = Texts(usage, "[", flags, " ", get_flag_options(t, "|"), "]");
else usage = Texts(usage, "[", flags, "=", get_flag_options(t, "|"), "]");
} else {
OptionalText_t flag = flagify(arg->name, false);
- assert(flag.length >= 0);
+ assert(flag.tag != TEXT_NONE);
OptionalText_t alias_flag = flagify(arg->alias, true);
if (t->tag == BoolType)
- usage = Texts(usage, "<--", flag, alias_flag.length >= 0 ? Texts("|", alias_flag) : EMPTY_TEXT,
+ usage = Texts(usage, "<--", flag, alias_flag.tag != TEXT_NONE ? Texts("|", alias_flag) : EMPTY_TEXT,
"|--no-", flag, ">");
else if (t->tag == EnumType) usage = Texts(usage, get_flag_options(t, "|"));
else if (t->tag == ListType) usage = Texts(usage, "[", flag, "...]");
diff --git a/src/compile/expressions.c b/src/compile/expressions.c
index a4603cd5..b9fafeb8 100644
--- a/src/compile/expressions.c
+++ b/src/compile/expressions.c
@@ -41,9 +41,9 @@ Text_t compile_empty(type_t *t) {
}
case ByteType: return Text("((Byte_t)0)");
case BoolType: return Text("((Bool_t)no)");
- case ListType: return Text("((List_t){})");
- case TableType: return Text("((Table_t){})");
- case TextType: return Text("Text(\"\")");
+ case ListType: return Text("EMPTY_LIST");
+ case TableType: return Text("EMPTY_TABLE");
+ case TextType: return Text("EMPTY_TEXT");
case CStringType: return Text("\"\"");
case PointerType: {
DeclareMatch(ptr, t, PointerType);
@@ -177,7 +177,7 @@ Text_t compile(env_t *env, ast_t *ast) {
}
case List: {
DeclareMatch(list, ast, List);
- if (!list->items) return Text("(List_t){.length=0}");
+ if (!list->items) return Text("EMPTY_LIST");
type_t *list_type = get_type(env, ast);
return compile_typed_list(env, ast, list_type);
@@ -185,8 +185,8 @@ Text_t compile(env_t *env, ast_t *ast) {
case Table: {
DeclareMatch(table, ast, Table);
if (!table->entries) {
- Text_t code = Text("((Table_t){");
- if (table->fallback) code = Texts(code, ".fallback=heap(", compile(env, table->fallback), ")");
+ Text_t code = Text("((Table_t){.entries=EMPTY_LIST");
+ if (table->fallback) code = Texts(code, ", .fallback=heap(", compile(env, table->fallback), ")");
return Texts(code, "})");
}
diff --git a/src/compile/functions.c b/src/compile/functions.c
index d2320e04..40e16e48 100644
--- a/src/compile/functions.c
+++ b/src/compile/functions.c
@@ -62,7 +62,7 @@ Text_t compile_convert_declaration(env_t *env, ast_t *ast) {
public
Text_t compile_arguments(env_t *env, ast_t *call_ast, arg_t *spec_args, arg_ast_t *call_args) {
- Table_t used_args = {};
+ Table_t used_args = EMPTY_TABLE;
Text_t code = EMPTY_TEXT;
env_t *default_scope = new (env_t);
*default_scope = *env;
@@ -263,7 +263,7 @@ Text_t compile_lambda(env_t *env, ast_t *ast) {
Table_t closed_vars = get_closed_vars(env, lambda->args, ast);
if (Table$length(closed_vars) > 0) { // Create a typedef for the lambda's closure userdata
Text_t def = Text("typedef struct {");
- for (int64_t i = 0; i < closed_vars.entries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)closed_vars.entries.length; i++) {
struct {
const char *name;
binding_t *b;
@@ -293,7 +293,7 @@ Text_t compile_lambda(env_t *env, ast_t *ast) {
userdata = Text("NULL");
} else {
userdata = Texts("new(", name, "$userdata_t");
- for (int64_t i = 0; i < closed_vars.entries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)closed_vars.entries.length; i++) {
struct {
const char *name;
binding_t *b;
@@ -596,7 +596,7 @@ Table_t get_closed_vars(env_t *env, arg_ast_t *args, ast_t *block) {
set_binding(body_scope, arg->name, arg_type, Texts("_$", arg->name));
}
- Table_t closed_vars = {};
+ Table_t closed_vars = EMPTY_TABLE;
add_closed_vars(&closed_vars, env, body_scope, block);
return closed_vars;
}
@@ -633,7 +633,7 @@ Text_t compile_function(env_t *env, Text_t name_code, ast_t *ast, Text_t *static
}
Text_t arg_signature = Text("(");
- Table_t used_names = {};
+ Table_t used_names = EMPTY_TABLE;
for (arg_ast_t *arg = args; arg; arg = arg->next) {
type_t *arg_type = get_arg_ast_type(env, arg);
arg_signature = Texts(arg_signature, compile_declaration(arg_type, Texts("_$", arg->name)));
@@ -712,7 +712,7 @@ Text_t compile_function(env_t *env, Text_t name_code, ast_t *ast, Text_t *static
assert(args);
OptionalInt64_t cache_size = Int64$parse(Text$from_str(Match(cache, Int)->str), NULL);
Text_t pop_code = EMPTY_TEXT;
- if (cache->tag == Int && !cache_size.is_none && cache_size.value > 0) {
+ if (cache->tag == Int && cache_size.has_value && cache_size.value > 0) {
// FIXME: this currently just deletes the first entry, but this
// should be more like a least-recently-used cache eviction policy
// or least-frequently-used
@@ -727,7 +727,7 @@ Text_t compile_function(env_t *env, Text_t name_code, ast_t *ast, Text_t *static
Text_t wrapper =
Texts(is_private ? EMPTY_TEXT : Text("public "), ret_type_code, " ", name_code, arg_signature,
"{\n"
- "static Table_t cache = {};\n",
+ "static Table_t cache = EMPTY_TABLE;\n",
"const TypeInfo_t *table_type = Table$info(", compile_type_info(arg_type), ", ",
compile_type_info(ret_t), ");\n",
compile_declaration(Type(PointerType, .pointed = ret_t), Text("cached")),
@@ -750,7 +750,7 @@ Text_t compile_function(env_t *env, Text_t name_code, ast_t *ast, Text_t *static
type_t *t = Type(StructType, .name = String("func$", get_line_number(ast->file, ast->start), "$args"),
.fields = fields, .env = env);
- int64_t num_fields = used_names.entries.length;
+ int64_t num_fields = (int64_t)used_names.entries.length;
const char *metamethods = is_packed_data(t) ? "PackedData$metamethods" : "Struct$metamethods";
Text_t args_typeinfo = Texts("((TypeInfo_t[1]){{.size=sizeof(args), "
".align=__alignof__(args), .metamethods=",
@@ -775,7 +775,7 @@ Text_t compile_function(env_t *env, Text_t name_code, ast_t *ast, Text_t *static
Text_t wrapper = Texts(
is_private ? EMPTY_TEXT : Text("public "), ret_type_code, " ", name_code, arg_signature,
"{\n"
- "static Table_t cache = {};\n",
+ "static Table_t cache = EMPTY_TABLE;\n",
args_type, " args = {", all_args,
"};\n"
"const TypeInfo_t *table_type = Table$info(",
diff --git a/src/compile/lists.c b/src/compile/lists.c
index e3aa951b..d9fb46a3 100644
--- a/src/compile/lists.c
+++ b/src/compile/lists.c
@@ -20,7 +20,7 @@ static ast_t *add_to_list_comprehension(ast_t *item, ast_t *subject) {
public
Text_t compile_typed_list(env_t *env, ast_t *ast, type_t *list_type) {
DeclareMatch(list, ast, List);
- if (!list->items) return Text("(List_t){.length=0}");
+ if (!list->items) return Text("EMPTY_LIST");
type_t *item_type = Match(list_type, ListType)->item_type;
@@ -48,7 +48,7 @@ list_comprehension: {
LiteralCode(Texts("&", comprehension_name), .type = Type(PointerType, .pointed = list_type, .is_stack = true));
Closure_t comp_action = {.fn = add_to_list_comprehension, .userdata = comprehension_var};
scope->comprehension_action = &comp_action;
- Text_t code = Texts("({ List_t ", comprehension_name, " = {};");
+ Text_t code = Texts("({ List_t ", comprehension_name, " = EMPTY_LIST;");
// set_binding(scope, comprehension_name, list_type, comprehension_name);
for (ast_list_t *item = list->items; item; item = item->next) {
if (item->ast->tag == Comprehension) code = Texts(code, "\n", compile_statement(scope, item->ast));
diff --git a/src/compile/optionals.c b/src/compile/optionals.c
index d74f0f31..bd5f861d 100644
--- a/src/compile/optionals.c
+++ b/src/compile/optionals.c
@@ -28,18 +28,17 @@ Text_t promote_to_optional(type_t *t, Text_t code) {
return code;
} else if (t->tag == IntType) {
switch (Match(t, IntType)->bits) {
- case TYPE_IBITS8: return Texts("((OptionalInt8_t){.value=", code, "})");
- case TYPE_IBITS16: return Texts("((OptionalInt16_t){.value=", code, "})");
- case TYPE_IBITS32: return Texts("((OptionalInt32_t){.value=", code, "})");
- case TYPE_IBITS64: return Texts("((OptionalInt64_t){.value=", code, "})");
- default: errx(1, "Unsupported in type: %s", type_to_text(t));
+ case TYPE_IBITS8: return Texts("((OptionalInt8_t){.has_value=true, .value=", code, "})");
+ case TYPE_IBITS16: return Texts("((OptionalInt16_t){.has_value=true, .value=", code, "})");
+ case TYPE_IBITS32: return Texts("((OptionalInt32_t){.has_value=true, .value=", code, "})");
+ case TYPE_IBITS64: return Texts("((OptionalInt64_t){.has_value=true, .value=", code, "})");
+ default: errx(1, "Unsupported in type: %s", Text$as_c_string(type_to_text(t)));
}
return code;
} else if (t->tag == ByteType) {
- return Texts("((OptionalByte_t){.value=", code, "})");
+ return Texts("((OptionalByte_t){.has_value=true, .value=", code, "})");
} else if (t->tag == StructType) {
- return Texts("({ ", compile_type(Type(OptionalType, .type = t)), " nonnull = {.value=", code,
- "}; nonnull.is_none = false; nonnull; })");
+ return Texts("((", compile_type(Type(OptionalType, .type = t)), "){.has_value=true, .value=", code, "})");
} else {
return code;
}
@@ -54,7 +53,7 @@ Text_t compile_none(type_t *t) {
if (t == NULL) compiler_err(NULL, NULL, NULL, "I can't compile a `none` value with no type");
if (t == PATH_TYPE) return Text("NONE_PATH");
- else if (t == PATH_TYPE_TYPE) return Text("((OptionalPathType_t){})");
+ else if (t == PATH_TYPE_TYPE) return Text("((OptionalPathType_t){.type = PATH_NONE})");
switch (t->tag) {
case BigIntType: return Text("NONE_INT");
@@ -77,7 +76,7 @@ Text_t compile_none(type_t *t) {
case PointerType: return Texts("((", compile_type(t), ")NULL)");
case ClosureType: return Text("NONE_CLOSURE");
case NumType: return Text("nan(\"none\")");
- case StructType: return Texts("((", compile_type(Type(OptionalType, .type = t)), "){.is_none=true})");
+ case StructType: return Texts("((", compile_type(Type(OptionalType, .type = t)), "){.has_value=false})");
case EnumType: {
env_t *enum_env = Match(t, EnumType)->env;
return Texts("((", compile_type(t), "){", namespace_name(enum_env, enum_env->namespace, Text("none")), "})");
@@ -99,11 +98,11 @@ Text_t check_none(type_t *t, Text_t value) {
else if (t->tag == ClosureType) return Texts("((", value, ").fn == NULL)");
else if (t->tag == NumType)
return Texts(Match(t, NumType)->bits == TYPE_NBITS64 ? "Num$isnan(" : "Num32$isnan(", value, ")");
- else if (t->tag == ListType) return Texts("((", value, ").length < 0)");
- else if (t->tag == TableType) return Texts("((", value, ").entries.length < 0)");
+ else if (t->tag == ListType) return Texts("((", value, ").data == NULL)");
+ else if (t->tag == TableType) return Texts("((", value, ").entries.data == NULL)");
else if (t->tag == BoolType) return Texts("((", value, ") == NONE_BOOL)");
- else if (t->tag == TextType) return Texts("((", value, ").length < 0)");
- else if (t->tag == IntType || t->tag == ByteType || t->tag == StructType) return Texts("(", value, ").is_none");
+ else if (t->tag == TextType) return Texts("((", value, ").tag == TEXT_NONE)");
+ else if (t->tag == IntType || t->tag == ByteType || t->tag == StructType) return Texts("!(", value, ").has_value");
else if (t->tag == EnumType) {
if (enum_has_fields(t)) return Texts("((", value, ").$tag == 0)");
else return Texts("((", value, ") == 0)");
diff --git a/src/compile/statements.c b/src/compile/statements.c
index 37eff680..156cc8c0 100644
--- a/src/compile/statements.c
+++ b/src/compile/statements.c
@@ -91,7 +91,7 @@ static Text_t _compile_statement(env_t *env, ast_t *ast) {
static int defer_id = 0;
env_t *defer_env = fresh_scope(env);
Text_t code = EMPTY_TEXT;
- for (int64_t i = 0; i < closed_vars.entries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)closed_vars.entries.length; i++) {
struct {
const char *name;
binding_t *b;
diff --git a/src/compile/tables.c b/src/compile/tables.c
index 814d81f5..2b6d3538 100644
--- a/src/compile/tables.c
+++ b/src/compile/tables.c
@@ -60,8 +60,8 @@ table_comprehension: {
ast_t *comprehension_var =
LiteralCode(Texts("&", comprehension_name), .type = Type(PointerType, .pointed = table_type, .is_stack = true));
- Text_t code = Texts("({ Table_t ", comprehension_name, " = {");
- if (table->fallback) code = Texts(code, ".fallback=heap(", compile(env, table->fallback), "), ");
+ Text_t code = Texts("({ Table_t ", comprehension_name, " = {.entries=EMPTY_LIST");
+ if (table->fallback) code = Texts(code, ", .fallback=heap(", compile(env, table->fallback), "), ");
code = Texts(code, "};");