aboutsummaryrefslogtreecommitdiff
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
parent126050a6357d7ec1fd9901256de50923b6dd7c49 (diff)
parent597699243a6f935231ad83e63d22bf6ff9e4e547 (diff)
Merge branch 'zero-nones' into dev
-rw-r--r--src/ast.c4
-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
-rw-r--r--src/environment.c6
-rw-r--r--src/formatter/args.c4
-rw-r--r--src/formatter/enums.c4
-rw-r--r--src/formatter/formatter.c6
-rw-r--r--src/formatter/types.c2
-rw-r--r--src/formatter/utils.c2
-rw-r--r--src/formatter/utils.h2
-rw-r--r--src/modules.c8
-rw-r--r--src/naming.c2
-rw-r--r--src/parse/files.c4
-rw-r--r--src/stdlib/bytes.c16
-rw-r--r--src/stdlib/cli.c28
-rw-r--r--src/stdlib/datatypes.h12
-rw-r--r--src/stdlib/integers.c26
-rw-r--r--src/stdlib/integers.h10
-rw-r--r--src/stdlib/lists.c174
-rw-r--r--src/stdlib/lists.h4
-rw-r--r--src/stdlib/metamethods.c7
-rw-r--r--src/stdlib/optionals.c8
-rw-r--r--src/stdlib/optionals.h6
-rw-r--r--src/stdlib/paths.c43
-rw-r--r--src/stdlib/pointers.c8
-rw-r--r--src/stdlib/tables.c62
-rw-r--r--src/stdlib/tables.h2
-rw-r--r--src/stdlib/text.c74
-rw-r--r--src/stdlib/text.h2
-rw-r--r--src/stdlib/types.h2
-rw-r--r--src/tomo.c47
-rw-r--r--src/typecheck.c12
37 files changed, 336 insertions, 326 deletions
diff --git a/src/ast.c b/src/ast.c
index 80127cf7..a5d0ba81 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -358,7 +358,7 @@ void visit_topologically(ast_list_t *asts, Closure_t fn) {
// - visiting typedefs' dependencies first
// - then function/variable declarations
- Table_t definitions = {};
+ Table_t definitions = EMPTY_TABLE;
for (ast_list_t *stmt = asts; stmt; stmt = stmt->next) {
if (stmt->ast->tag == StructDef) {
DeclareMatch(def, stmt->ast, StructDef);
@@ -373,7 +373,7 @@ void visit_topologically(ast_list_t *asts, Closure_t fn) {
}
void (*visit)(void *, ast_t *) = (void *)fn.fn;
- Table_t visited = {};
+ Table_t visited = EMPTY_TABLE;
// First: 'use' statements in order:
for (ast_list_t *stmt = asts; stmt; stmt = stmt->next) {
if (stmt->ast->tag == Use) visit(fn.userdata, stmt->ast);
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, "};");
diff --git a/src/environment.c b/src/environment.c
index c29aa29d..3f07787e 100644
--- a/src/environment.c
+++ b/src/environment.c
@@ -405,7 +405,7 @@ env_t *global_env(bool source_mapping) {
binding_t *type_binding = Table$str_get(*env->globals, global_types[i].name);
assert(type_binding);
env_t *ns_env = Match(type_binding->type, TypeInfoType)->env;
- for (int64_t j = 0; j < global_types[i].namespace.length; j++) {
+ for (int64_t j = 0; j < (int64_t)global_types[i].namespace.length; j++) {
ns_entry_t *entry = global_types[i].namespace.data + j * global_types[i].namespace.stride;
type_t *type = parse_type_string(ns_env, entry->type_str);
if (!type) compiler_err(NULL, NULL, NULL, "Couldn't parse type string: ", entry->type_str);
@@ -715,14 +715,14 @@ PUREFUNC binding_t *get_constructor(env_t *env, type_t *t, arg_ast_t *args, bool
List_t constructors = type_env->namespace->constructors;
// Prioritize exact matches:
call_opts_t options = {.promotion = false, .underscores = allow_underscores};
- for (int64_t i = constructors.length - 1; i >= 0; i--) {
+ for (int64_t i = (int64_t)constructors.length - 1; i >= 0; i--) {
binding_t *constructor = constructors.data + i * constructors.stride;
DeclareMatch(fn, constructor->type, FunctionType);
if (type_eq(fn->ret, t) && is_valid_call(env, fn->args, args, options)) return constructor;
}
// Fall back to promotion:
options.promotion = true;
- for (int64_t i = constructors.length - 1; i >= 0; i--) {
+ for (int64_t i = (int64_t)constructors.length - 1; i >= 0; i--) {
binding_t *constructor = constructors.data + i * constructors.stride;
DeclareMatch(fn, constructor->type, FunctionType);
if (type_eq(fn->ret, t) && is_valid_call(env, fn->args, args, options)) return constructor;
diff --git a/src/formatter/args.c b/src/formatter/args.c
index 997a1e39..9d1a2f71 100644
--- a/src/formatter/args.c
+++ b/src/formatter/args.c
@@ -19,7 +19,7 @@ OptionalText_t format_inline_arg(arg_ast_t *arg, Table_t comments) {
Text_t format_arg(arg_ast_t *arg, Table_t comments, Text_t indent) {
OptionalText_t inline_arg = format_inline_arg(arg, comments);
- if (inline_arg.length >= 0 && inline_arg.length <= MAX_WIDTH) return inline_arg;
+ if (inline_arg.tag != TEXT_NONE && inline_arg.length <= MAX_WIDTH) return inline_arg;
if (arg->name == NULL && arg->value) return format_code(arg->value, comments, indent);
Text_t code = Text$from_str(arg->name);
if (arg->type) code = Texts(code, ":", format_type(arg->type));
@@ -43,7 +43,7 @@ OptionalText_t format_inline_args(arg_ast_t *args, Table_t comments) {
Text_t format_args(arg_ast_t *args, Table_t comments, Text_t indent) {
OptionalText_t inline_args = format_inline_args(args, comments);
- if (inline_args.length >= 0 && inline_args.length <= MAX_WIDTH) return inline_args;
+ if (inline_args.tag != TEXT_NONE && inline_args.length <= MAX_WIDTH) return inline_args;
Text_t code = EMPTY_TEXT;
for (arg_ast_t *arg = args; arg; arg = arg->next) {
if (arg->name && arg->next && arg->type == arg->next->type && arg->value == arg->next->value) {
diff --git a/src/formatter/enums.c b/src/formatter/enums.c
index 893f055b..e497e20c 100644
--- a/src/formatter/enums.c
+++ b/src/formatter/enums.c
@@ -20,7 +20,7 @@ OptionalText_t format_inline_tag(tag_ast_t *tag, Table_t comments) {
Text_t format_tag(tag_ast_t *tag, Table_t comments, Text_t indent) {
OptionalText_t inline_tag = format_inline_tag(tag, comments);
- if (inline_tag.length >= 0) return inline_tag;
+ if (inline_tag.tag != TEXT_NONE) return inline_tag;
Text_t code = Text$from_str(tag->name);
if (tag->fields || tag->secret) {
code = Texts(code, "(", format_args(tag->fields, comments, Texts(indent, single_indent)));
@@ -42,7 +42,7 @@ OptionalText_t format_inline_tags(tag_ast_t *tags, Table_t comments) {
Text_t format_tags(tag_ast_t *tags, Table_t comments, Text_t indent) {
OptionalText_t inline_tags = format_inline_tags(tags, comments);
- if (inline_tags.length >= 0) return inline_tags;
+ if (inline_tags.tag != TEXT_NONE) return inline_tags;
Text_t code = EMPTY_TEXT;
for (; tags; tags = tags->next) {
add_line(&code, Texts(format_tag(tags, comments, indent), ","), indent);
diff --git a/src/formatter/formatter.c b/src/formatter/formatter.c
index 2d220493..9ff328d0 100644
--- a/src/formatter/formatter.c
+++ b/src/formatter/formatter.c
@@ -89,7 +89,7 @@ static Text_t format_text(text_opts_t opts, ast_list_t *chunks, Table_t comments
List_t lines = Text$lines(literal);
if (lines.length == 0) continue;
current_line = Texts(current_line, Text$escaped(*(Text_t *)lines.data, false, opts.interp));
- for (int64_t i = 1; i < lines.length; i += 1) {
+ for (int64_t i = 1; i < (int64_t)lines.length; i += 1) {
add_line(&code, current_line, Texts(indent, single_indent));
current_line = Text$escaped(*(Text_t *)(lines.data + i * lines.stride), false, opts.interp);
}
@@ -402,7 +402,7 @@ PUREFUNC static int64_t trailing_line_len(Text_t text) {
Text_t format_code(ast_t *ast, Table_t comments, Text_t indent) {
OptionalText_t inlined = format_inline_code(ast, comments);
- bool inlined_fits = (inlined.length >= 0 && indent.length + inlined.length <= MAX_WIDTH);
+ bool inlined_fits = (inlined.tag != TEXT_NONE && indent.length + inlined.length <= MAX_WIDTH);
switch (ast->tag) {
/*multiline*/ case Unknown:
@@ -758,7 +758,7 @@ Text_t format_code(ast_t *ast, Table_t comments, Text_t indent) {
/*multiline*/ case Int:
/*multiline*/ case Num:
/*multiline*/ case Var: {
- assert(inlined.length >= 0);
+ assert(inlined.tag != TEXT_NONE);
return inlined;
}
/*multiline*/ case FunctionCall: {
diff --git a/src/formatter/types.c b/src/formatter/types.c
index 3c77fa7d..670405f6 100644
--- a/src/formatter/types.c
+++ b/src/formatter/types.c
@@ -22,7 +22,7 @@ Text_t format_type(type_ast_t *type) {
Text_t code = Texts("{", format_type(table->key), ":", format_type(table->value));
if (table->default_value) {
OptionalText_t val = format_inline_code(table->default_value, (Table_t){});
- assert(val.length >= 0);
+ assert(val.tag != TEXT_NONE);
code = Texts(code, "=", val);
}
return Texts(code, "}");
diff --git a/src/formatter/utils.c b/src/formatter/utils.c
index 9cd0227d..9829df4b 100644
--- a/src/formatter/utils.c
+++ b/src/formatter/utils.c
@@ -35,7 +35,7 @@ OptionalText_t next_comment(Table_t comments, const char **pos, const char *end)
bool range_has_comment(const char *start, const char *end, Table_t comments) {
OptionalText_t comment = next_comment(comments, &start, end);
- return (comment.length >= 0);
+ return (comment.tag != TEXT_NONE);
}
CONSTFUNC int suggested_blank_lines(ast_t *first, ast_t *second) {
diff --git a/src/formatter/utils.h b/src/formatter/utils.h
index 880da0a9..ba96ed50 100644
--- a/src/formatter/utils.h
+++ b/src/formatter/utils.h
@@ -13,7 +13,7 @@
#define must(expr) \
({ \
OptionalText_t _expr = expr; \
- if (_expr.length < 0) return NONE_TEXT; \
+ if (_expr.tag == TEXT_NONE) return NONE_TEXT; \
(Text_t) _expr; \
})
diff --git a/src/modules.c b/src/modules.c
index 08550f2e..9ebdca09 100644
--- a/src/modules.c
+++ b/src/modules.c
@@ -51,7 +51,7 @@ bool install_from_modules_ini(Path_t ini_file, bool ask_confirmation) {
if (by_line.fn == NULL) return false;
OptionalText_t (*next_line)(void *) = by_line.fn;
module_info_t info = {};
- for (Text_t line; (line = next_line(by_line.userdata)).length >= 0;) {
+ for (OptionalText_t line; (line = next_line(by_line.userdata)).tag != TEXT_NONE;) {
char *line_str = Text$as_c_string(line);
const char *next_section = NULL;
if (!strparse(line_str, "[", &next_section, "]")) {
@@ -78,13 +78,13 @@ static void read_modules_ini(Path_t ini_file, module_info_t *info) {
if (by_line.fn == NULL) return;
OptionalText_t (*next_line)(void *) = by_line.fn;
find_section:;
- for (Text_t line; (line = next_line(by_line.userdata)).length >= 0;) {
+ for (OptionalText_t line; (line = next_line(by_line.userdata)).tag != TEXT_NONE;) {
char *line_str = Text$as_c_string(line);
if (line_str[0] == '[' && strncmp(line_str + 1, info->name, strlen(info->name)) == 0
&& line_str[1 + strlen(info->name)] == ']')
break;
}
- for (Text_t line; (line = next_line(by_line.userdata)).length >= 0;) {
+ for (OptionalText_t line; (line = next_line(by_line.userdata)).tag != TEXT_NONE;) {
char *line_str = Text$as_c_string(line);
if (line_str[0] == '[') goto find_section;
if (!strparse(line_str, "version=", &info->version) || !strparse(line_str, "url=", &info->url)
@@ -95,7 +95,7 @@ find_section:;
}
module_info_t get_used_module_info(ast_t *use) {
- static Table_t cache = {};
+ static Table_t cache = EMPTY_TABLE;
TypeInfo_t *cache_type = Table$info(Pointer$info("@", &Memory$info), Pointer$info("@", &Memory$info));
module_info_t **cached = Table$get(cache, &use, cache_type);
if (cached) return **cached;
diff --git a/src/naming.c b/src/naming.c
index 38357039..484e1998 100644
--- a/src/naming.c
+++ b/src/naming.c
@@ -112,6 +112,6 @@ Text_t get_id_suffix(const char *filename) {
}
Path_t id_file = Path$child(build_dir, Texts(Path$base_name(path), Text$from_str(".id")));
OptionalText_t id = Path$read(id_file);
- if (id.length < 0) err(1, "Could not read ID file: %s", id_file);
+ if (id.tag == TEXT_NONE) err(1, "Could not read ID file: %s", Path$as_c_string(id_file));
return Texts("$", id);
}
diff --git a/src/parse/files.c b/src/parse/files.c
index caecbbe8..5e0dc29c 100644
--- a/src/parse/files.c
+++ b/src/parse/files.c
@@ -17,7 +17,6 @@
#include "statements.h"
#include "text.h"
#include "typedefs.h"
-#include "types.h"
#include "utils.h"
// The cache of {filename -> parsed AST} will hold at most this many entries:
@@ -67,7 +66,7 @@ ast_t *parse_file(const char *path, jmp_buf *on_err) {
// hold more than PARSE_CACHE_SIZE entries (see below), but each entry's
// AST holds onto a reference to the file it came from, so they could
// potentially be somewhat large.
- static Table_t cached = {};
+ static Table_t cached = EMPTY_TABLE;
ast_t *ast = Table$str_get(cached, path);
if (ast) return ast;
@@ -106,6 +105,7 @@ ast_t *parse_file(const char *path, jmp_buf *on_err) {
const char *path;
ast_t *ast;
} *to_remove = Table$entry(cached, 1);
+ assert(to_remove);
Table$str_remove(&cached, to_remove->path);
}
diff --git a/src/stdlib/bytes.c b/src/stdlib/bytes.c
index db12e501..ab689ae4 100644
--- a/src/stdlib/bytes.c
+++ b/src/stdlib/bytes.c
@@ -36,7 +36,7 @@ public
OptionalByte_t Byte$parse(Text_t text, Text_t *remainder) {
OptionalInt_t full_int = Int$parse(text, remainder);
if (full_int.small != 0L && Int$compare_value(full_int, I(0)) >= 0 && Int$compare_value(full_int, I(255)) <= 0) {
- return (OptionalByte_t){.value = Byte$from_int(full_int, true)};
+ return (OptionalByte_t){.has_value = true, .value = Byte$from_int(full_int, true)};
} else {
return NONE_BYTE;
}
@@ -86,12 +86,12 @@ typedef struct {
static OptionalByte_t _next_Byte(ByteRange_t *info) {
OptionalByte_t i = info->current;
- if (!i.is_none) {
+ if (i.has_value) {
Byte_t next;
bool overflow = __builtin_add_overflow(i.value, info->step, &next);
- if (overflow || (!info->last.is_none && (info->step >= 0 ? next > info->last.value : next < info->last.value)))
- info->current = (OptionalByte_t){.is_none = true};
- else info->current = (OptionalByte_t){.value = next};
+ if (overflow || (info->last.has_value && (info->step >= 0 ? next > info->last.value : next < info->last.value)))
+ info->current = (OptionalByte_t){.has_value = false};
+ else info->current = (OptionalByte_t){.has_value = true, .value = next};
}
return i;
}
@@ -99,9 +99,9 @@ static OptionalByte_t _next_Byte(ByteRange_t *info) {
public
CONSTFUNC Closure_t Byte$to(Byte_t first, Byte_t last, OptionalInt8_t step) {
ByteRange_t *range = GC_MALLOC(sizeof(ByteRange_t));
- range->current = (OptionalByte_t){.value = first};
- range->last = (OptionalByte_t){.value = last};
- range->step = step.is_none ? (last >= first ? 1 : -1) : step.value;
+ range->current = (OptionalByte_t){.has_value = true, .value = first};
+ range->last = (OptionalByte_t){.has_value = true, .value = last};
+ range->step = step.has_value ? step.value : (last >= first ? 1 : -1);
return (Closure_t){.fn = _next_Byte, .userdata = range};
}
diff --git a/src/stdlib/cli.c b/src/stdlib/cli.c
index 62174f19..d5bb0ea2 100644
--- a/src/stdlib/cli.c
+++ b/src/stdlib/cli.c
@@ -45,24 +45,24 @@ static bool parse_single_arg(const TypeInfo_t *info, char *arg, void *dest) {
return parsed.small != 0;
} else if (info == &Int64$info) {
OptionalInt64_t parsed = Int64$parse(Text$from_str(arg), NULL);
- if (!parsed.is_none) *(OptionalInt64_t *)dest = parsed;
- return !parsed.is_none;
+ if (parsed.has_value) *(OptionalInt64_t *)dest = parsed;
+ return parsed.has_value;
} else if (info == &Int32$info) {
OptionalInt32_t parsed = Int32$parse(Text$from_str(arg), NULL);
- if (!parsed.is_none) *(OptionalInt32_t *)dest = parsed;
- return !parsed.is_none;
+ if (parsed.has_value) *(OptionalInt32_t *)dest = parsed;
+ return parsed.has_value;
} else if (info == &Int16$info) {
OptionalInt16_t parsed = Int16$parse(Text$from_str(arg), NULL);
- if (!parsed.is_none) *(OptionalInt16_t *)dest = parsed;
- return !parsed.is_none;
+ if (parsed.has_value) *(OptionalInt16_t *)dest = parsed;
+ return parsed.has_value;
} else if (info == &Int8$info) {
OptionalInt8_t parsed = Int8$parse(Text$from_str(arg), NULL);
- if (!parsed.is_none) *(OptionalInt8_t *)dest = parsed;
- return !parsed.is_none;
+ if (parsed.has_value) *(OptionalInt8_t *)dest = parsed;
+ return parsed.has_value;
} else if (info == &Byte$info) {
OptionalByte_t parsed = Byte$parse(Text$from_str(arg), NULL);
- if (!parsed.is_none) *(OptionalByte_t *)dest = parsed;
- return !parsed.is_none;
+ if (parsed.has_value) *(OptionalByte_t *)dest = parsed;
+ return parsed.has_value;
} else if (info == &Bool$info) {
OptionalBool_t parsed = Bool$parse(Text$from_str(arg), NULL);
if (parsed != NONE_BOOL) *(OptionalBool_t *)dest = parsed;
@@ -124,9 +124,10 @@ static List_t parse_list(const TypeInfo_t *item_info, int n, char *args[]) {
if ((padded_size % item_info->align) > 0)
padded_size = padded_size + item_info->align - (padded_size % item_info->align);
+ uint64_t u = (uint64_t)n;
List_t items = {
.stride = padded_size,
- .length = n,
+ .length = u,
.data = GC_MALLOC((size_t)(padded_size * n)),
};
for (int i = 0; i < n; i++) {
@@ -145,9 +146,10 @@ static Table_t parse_table(const TypeInfo_t *table, int n, char *args[]) {
padded_size += value->size;
if ((padded_size % key->align) > 0) padded_size = padded_size + key->align - (padded_size % key->align);
+ uint64_t u = (uint64_t)n;
List_t entries = {
.stride = padded_size,
- .length = n,
+ .length = u,
.data = GC_MALLOC((size_t)(padded_size * n)),
};
for (int i = 0; i < n; i++) {
@@ -378,7 +380,7 @@ void _tomo_parse_args(int argc, char *argv[], Text_t usage, Text_t help, const c
for (int s = 0; s < spec_len; s++) {
if (!populated_args[s] && spec[s].required) {
- if (spec[s].type->tag == ListInfo) *(OptionalList_t *)spec[s].dest = (List_t){};
+ if (spec[s].type->tag == ListInfo) *(OptionalList_t *)spec[s].dest = EMPTY_LIST;
else if (spec[s].type->tag == TableInfo) *(OptionalTable_t *)spec[s].dest = (Table_t){};
else print_err("The required argument '", spec[s].name, "' was not provided\n", usage);
}
diff --git a/src/stdlib/datatypes.h b/src/stdlib/datatypes.h
index 373cbc47..fc665401 100644
--- a/src/stdlib/datatypes.h
+++ b/src/stdlib/datatypes.h
@@ -41,7 +41,7 @@ typedef struct {
// structs can be passed in two 64-bit registers. C will handle doing the
// bit arithmetic to extract the necessary values, which is cheaper than
// spilling onto the stack and needing to retrieve data from the stack.
- int64_t length : LIST_LENGTH_BITS;
+ uint64_t length : LIST_LENGTH_BITS;
uint64_t free : LIST_FREE_BITS;
bool atomic : LIST_ATOMIC_BITS;
uint8_t data_refcount : LIST_REFCOUNT_BITS;
@@ -73,11 +73,11 @@ typedef struct {
void *fn, *userdata;
} Closure_t;
-enum text_type { TEXT_ASCII, TEXT_GRAPHEMES, TEXT_CONCAT, TEXT_BLOB };
+enum text_type { TEXT_NONE, TEXT_ASCII, TEXT_GRAPHEMES, TEXT_CONCAT, TEXT_BLOB };
typedef struct Text_s {
- int64_t length : 54; // Number of grapheme clusters
- uint8_t tag : 2;
+ uint64_t length : 53; // Number of grapheme clusters
+ uint8_t tag : 3;
uint8_t depth : 8;
union {
struct {
@@ -117,7 +117,7 @@ typedef struct {
typedef struct {
Byte_t value;
- bool is_none : 1;
+ bool has_value : 1;
} OptionalByte_t;
-#define NONE_BYTE ((OptionalByte_t){.is_none = true})
+#define NONE_BYTE ((OptionalByte_t){.has_value = false})
diff --git a/src/stdlib/integers.c b/src/stdlib/integers.c
index 863bb42d..e7a58ef3 100644
--- a/src/stdlib/integers.c
+++ b/src/stdlib/integers.c
@@ -674,43 +674,43 @@ void Int32$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_
} KindOfInt##Range_t; \
static Optional##KindOfInt##_t _next_##KindOfInt(KindOfInt##Range_t *info) { \
Optional##KindOfInt##_t i = info->current; \
- if (!i.is_none) { \
+ if (i.has_value) { \
KindOfInt##_t next; \
bool overflow = __builtin_add_overflow(i.value, info->step, &next); \
if (overflow \
- || (!info->last.is_none && (info->step >= 0 ? next > info->last.value : next < info->last.value))) \
- info->current = (Optional##KindOfInt##_t){.is_none = true}; \
- else info->current = (Optional##KindOfInt##_t){.value = next}; \
+ || (info->last.has_value && (info->step >= 0 ? next > info->last.value : next < info->last.value))) \
+ info->current = (Optional##KindOfInt##_t){.has_value = false}; \
+ else info->current = (Optional##KindOfInt##_t){.has_value = true, .value = next}; \
} \
return i; \
} \
public \
to_attr Closure_t KindOfInt##$to(c_type first, c_type last, Optional##KindOfInt##_t step) { \
KindOfInt##Range_t *range = GC_MALLOC(sizeof(KindOfInt##Range_t)); \
- range->current = (Optional##KindOfInt##_t){.value = first}; \
- range->last = (Optional##KindOfInt##_t){.value = last}; \
- range->step = step.is_none ? (last >= first ? 1 : -1) : step.value; \
+ range->current = (Optional##KindOfInt##_t){.has_value = true, .value = first}; \
+ range->last = (Optional##KindOfInt##_t){.has_value = true, .value = last}; \
+ range->step = step.has_value ? step.value : (last >= first ? 1 : -1); \
return (Closure_t){.fn = _next_##KindOfInt, .userdata = range}; \
} \
public \
to_attr Closure_t KindOfInt##$onward(c_type first, c_type step) { \
KindOfInt##Range_t *range = GC_MALLOC(sizeof(KindOfInt##Range_t)); \
- range->current = (Optional##KindOfInt##_t){.value = first}; \
- range->last = (Optional##KindOfInt##_t){.is_none = true}; \
+ range->current = (Optional##KindOfInt##_t){.has_value = true, .value = first}; \
+ range->last = (Optional##KindOfInt##_t){.has_value = false}; \
range->step = step; \
return (Closure_t){.fn = _next_##KindOfInt, .userdata = range}; \
} \
public \
PUREFUNC Optional##KindOfInt##_t KindOfInt##$parse(Text_t text, Text_t *remainder) { \
OptionalInt_t full_int = Int$parse(text, remainder); \
- if (full_int.small == 0L) return (Optional##KindOfInt##_t){.is_none = true}; \
+ if (full_int.small == 0L) return (Optional##KindOfInt##_t){.has_value = false}; \
if (Int$compare_value(full_int, I(min_val)) < 0) { \
- return (Optional##KindOfInt##_t){.is_none = true}; \
+ return (Optional##KindOfInt##_t){.has_value = false}; \
} \
if (Int$compare_value(full_int, I(max_val)) > 0) { \
- return (Optional##KindOfInt##_t){.is_none = true}; \
+ return (Optional##KindOfInt##_t){.has_value = false}; \
} \
- return (Optional##KindOfInt##_t){.value = KindOfInt##$from_int(full_int, true)}; \
+ return (Optional##KindOfInt##_t){.has_value = true, .value = KindOfInt##$from_int(full_int, true)}; \
} \
public \
CONSTFUNC c_type KindOfInt##$gcd(c_type x, c_type y) { \
diff --git a/src/stdlib/integers.h b/src/stdlib/integers.h
index 34195d23..7eafd134 100644
--- a/src/stdlib/integers.h
+++ b/src/stdlib/integers.h
@@ -19,7 +19,7 @@
#define DEFINE_INT_TYPE(c_type, type_name) \
typedef struct { \
c_type value; \
- bool is_none : 1; \
+ bool has_value : 1; \
} Optional##type_name##_t; \
Text_t type_name##$as_text(const void *i, bool colorize, const TypeInfo_t *type); \
Text_t type_name##$value_as_text(c_type i); \
@@ -69,10 +69,10 @@ DEFINE_INT_TYPE(int16_t, Int16)
DEFINE_INT_TYPE(int8_t, Int8)
#undef DEFINE_INT_TYPE
-#define NONE_INT64 ((OptionalInt64_t){.is_none = true})
-#define NONE_INT32 ((OptionalInt32_t){.is_none = true})
-#define NONE_INT16 ((OptionalInt16_t){.is_none = true})
-#define NONE_INT8 ((OptionalInt8_t){.is_none = true})
+#define NONE_INT64 ((OptionalInt64_t){.has_value = false})
+#define NONE_INT32 ((OptionalInt32_t){.has_value = false})
+#define NONE_INT16 ((OptionalInt16_t){.has_value = false})
+#define NONE_INT8 ((OptionalInt8_t){.has_value = false})
#define Int64$abs(...) I64(labs(__VA_ARGS__))
#define Int32$abs(...) I32(abs(__VA_ARGS__))
diff --git a/src/stdlib/lists.c b/src/stdlib/lists.c
index bae79dfd..516f37e2 100644
--- a/src/stdlib/lists.c
+++ b/src/stdlib/lists.c
@@ -18,6 +18,9 @@
// Use inline version of siphash code:
#include "siphash-internals.h"
+public
+char _EMPTY_LIST_SENTINEL = '\0';
+
PUREFUNC static INLINE int64_t get_padded_item_size(const TypeInfo_t *info) {
int64_t size = info->ListInfo.item->size;
if (info->ListInfo.item->align > 1 && size % info->ListInfo.item->align) errx(1, "Item size is not padded!");
@@ -35,7 +38,7 @@ void List$compact(List_t *list, int64_t padded_item_size) {
if ((int64_t)list->stride == padded_item_size) {
memcpy(copy, list->data, (size_t)list->length * (size_t)padded_item_size);
} else {
- for (int64_t i = 0; i < list->length; i++)
+ for (int64_t i = 0; i < (int64_t)list->length; i++)
memcpy(copy + i * padded_item_size, list->data + list->stride * i, (size_t)padded_item_size);
}
}
@@ -50,7 +53,7 @@ void List$compact(List_t *list, int64_t padded_item_size) {
public
void List$insert(List_t *list, const void *item, Int_t int_index, int64_t padded_item_size) {
int64_t index = Int64$from_int(int_index, false);
- if (index <= 0) index = list->length + index + 1;
+ if (index <= 0) index = (int64_t)list->length + index + 1;
if (index < 1) index = 1;
else if (index > (int64_t)list->length + 1)
@@ -74,9 +77,9 @@ void List$insert(List_t *list, const void *item, Int_t int_index, int64_t padded
list->data_refcount = 0;
list->stride = padded_item_size;
} else {
- if (index != list->length + 1) {
- assert(list->length >= index);
- size_t size = (size_t)((list->length - index + 1) * padded_item_size);
+ if (index != (int64_t)list->length + 1) {
+ assert((int64_t)list->length >= index);
+ size_t size = (size_t)(((int64_t)list->length - index + 1) * padded_item_size);
assert(size < SIZE_MAX);
memmove(list->data + index * padded_item_size, list->data + (index - 1) * padded_item_size, size);
}
@@ -98,7 +101,7 @@ void List$insert_all(List_t *list, List_t to_insert, Int_t int_index, int64_t pa
return;
}
- if (index < 1) index = list->length + index + 1;
+ if (index < 1) index = (int64_t)list->length + index + 1;
if (index < 1) index = 1;
else if (index > (int64_t)list->length + 1)
@@ -110,15 +113,15 @@ void List$insert_all(List_t *list, List_t to_insert, Int_t int_index, int64_t pa
// If we can fit this within the list's preallocated free space, do that:
list->free -= to_insert.length;
list->length += to_insert.length;
- if (index != list->length + 1)
+ if (index != (int64_t)list->length + 1)
memmove((void *)list->data + index * padded_item_size, list->data + (index - 1) * padded_item_size,
- (size_t)((list->length - index + to_insert.length - 1) * padded_item_size));
- for (int64_t i = 0; i < to_insert.length; i++)
+ (size_t)(((int64_t)list->length - index + (int64_t)to_insert.length - 1) * padded_item_size));
+ for (int64_t i = 0; i < (int64_t)to_insert.length; i++)
memcpy((void *)list->data + (index - 1 + i) * padded_item_size, to_insert.data + i * to_insert.stride,
(size_t)padded_item_size);
} else {
// Otherwise, allocate a new chunk of memory for the list and populate it:
- int64_t new_len = list->length + to_insert.length;
+ int64_t new_len = (int64_t)list->length + (int64_t)to_insert.length;
list->free = MIN(LIST_MAX_FREE_ENTRIES, MAX(8, new_len / 4));
void *data = list->atomic ? GC_MALLOC_ATOMIC((size_t)((new_len + list->free) * padded_item_size))
: GC_MALLOC((size_t)((new_len + list->free) * padded_item_size));
@@ -139,8 +142,8 @@ void List$insert_all(List_t *list, List_t to_insert, Int_t int_index, int64_t pa
// Copy `to_insert`
if (to_insert.stride == padded_item_size) {
- memcpy(p, to_insert.data, (size_t)(to_insert.length * padded_item_size));
- p += to_insert.length * padded_item_size;
+ memcpy(p, to_insert.data, (size_t)((int64_t)to_insert.length * padded_item_size));
+ p += (int64_t)to_insert.length * padded_item_size;
} else {
for (int64_t i = 0; i < index - 1; i++) {
memcpy(p, to_insert.data + to_insert.stride * i, (size_t)padded_item_size);
@@ -149,19 +152,19 @@ void List$insert_all(List_t *list, List_t to_insert, Int_t int_index, int64_t pa
}
// Copy last chunk of `list` if needed:
- if (index < list->length + 1) {
+ if (index < (int64_t)list->length + 1) {
if (list->stride == padded_item_size) {
memcpy(p, list->data + padded_item_size * (index - 1),
- (size_t)((list->length - index + 1) * padded_item_size));
- p += (list->length - index + 1) * padded_item_size;
+ (size_t)(((int64_t)list->length - index + 1) * padded_item_size));
+ p += ((int64_t)list->length - index + 1) * padded_item_size;
} else {
- for (int64_t i = index - 1; i < list->length - 1; i++) {
+ for (int64_t i = index - 1; i < (int64_t)list->length - 1; i++) {
memcpy(p, list->data + list->stride * i, (size_t)padded_item_size);
p += padded_item_size;
}
}
}
- list->length = new_len;
+ list->length = (uint64_t)new_len;
list->stride = padded_item_size;
list->data = data;
list->data_refcount = 0;
@@ -171,20 +174,20 @@ void List$insert_all(List_t *list, List_t to_insert, Int_t int_index, int64_t pa
public
void List$remove_at(List_t *list, Int_t int_index, Int_t int_count, int64_t padded_item_size) {
int64_t index = Int64$from_int(int_index, false);
- if (index < 1) index = list->length + index + 1;
+ if (index < 1) index = (int64_t)list->length + index + 1;
int64_t count = Int64$from_int(int_count, false);
if (index < 1 || index > (int64_t)list->length || count < 1) return;
- if (count > list->length - index + 1) count = (list->length - index) + 1;
+ if (count > (int64_t)list->length - index + 1) count = ((int64_t)list->length - index) + 1;
if (index == 1) {
list->data += list->stride * count;
- } else if (index + count > list->length) {
+ } else if (index + count > (int64_t)list->length) {
list->free += count;
} else if (list->data_refcount != 0 || (int64_t)list->stride != padded_item_size) {
- void *copy = list->atomic ? GC_MALLOC_ATOMIC((size_t)((list->length - 1) * padded_item_size))
- : GC_MALLOC((size_t)((list->length - 1) * padded_item_size));
+ void *copy = list->atomic ? GC_MALLOC_ATOMIC((size_t)(((int64_t)list->length - 1) * padded_item_size))
+ : GC_MALLOC((size_t)(((int64_t)list->length - 1) * padded_item_size));
for (int64_t src = 1, dest = 1; src <= (int64_t)list->length; src++) {
if (src < index || src >= index + count) {
memcpy(copy + (dest - 1) * padded_item_size, list->data + list->stride * (src - 1),
@@ -198,10 +201,10 @@ void List$remove_at(List_t *list, Int_t int_index, Int_t int_count, int64_t padd
} else {
memmove((void *)list->data + (index - 1) * padded_item_size,
list->data + (index - 1 + count) * padded_item_size,
- (size_t)((list->length - index + count - 1) * padded_item_size));
+ (size_t)(((int64_t)list->length - index + count - 1) * padded_item_size));
list->free += count;
}
- list->length -= count;
+ list->length -= (uint64_t)count;
if (list->length == 0) list->data = NULL;
}
@@ -211,7 +214,7 @@ void List$remove_item(List_t *list, void *item, Int_t max_removals, const TypeIn
const Int_t ZERO = (Int_t){.small = (0 << 2) | 1};
const Int_t ONE = (Int_t){.small = (1 << 2) | 1};
const TypeInfo_t *item_type = type->ListInfo.item;
- for (int64_t i = 0; i < list->length;) {
+ for (int64_t i = 0; i < (int64_t)list->length;) {
if (max_removals.small == ZERO.small) // zero
break;
@@ -227,7 +230,7 @@ void List$remove_item(List_t *list, void *item, Int_t max_removals, const TypeIn
public
OptionalInt_t List$find(List_t list, void *item, const TypeInfo_t *type) {
const TypeInfo_t *item_type = type->ListInfo.item;
- for (int64_t i = 0; i < list.length; i++) {
+ for (int64_t i = 0; i < (int64_t)list.length; i++) {
if (generic_equal(item, list.data + i * list.stride, item_type)) return I(i + 1);
}
return NONE_INT;
@@ -236,7 +239,7 @@ OptionalInt_t List$find(List_t list, void *item, const TypeInfo_t *type) {
public
OptionalInt_t List$first(List_t list, Closure_t predicate) {
bool (*is_good)(void *, void *) = (void *)predicate.fn;
- for (int64_t i = 0; i < list.length; i++) {
+ for (int64_t i = 0; i < (int64_t)list.length; i++) {
if (is_good(list.data + i * list.stride, predicate.userdata)) return I(i + 1);
}
return NONE_INT;
@@ -300,9 +303,9 @@ void List$shuffle(List_t *list, OptionalClosure_t random_int64, int64_t padded_i
typedef int64_t (*rng_fn_t)(int64_t, int64_t, void *);
rng_fn_t rng_fn = random_int64.fn ? (rng_fn_t)random_int64.fn : _default_random_int64;
char tmp[padded_item_size];
- for (int64_t i = list->length - 1; i > 1; i--) {
+ for (int64_t i = (int64_t)list->length - 1; i > 1; i--) {
int64_t j = rng_fn(0, i, random_int64.userdata);
- if unlikely (j < 0 || j > list->length - 1)
+ if unlikely (j < 0 || j > (int64_t)list->length - 1)
fail("The provided random number function returned an invalid value: ", j, " (not between 0 and ", i, ")");
memcpy(tmp, list->data + i * padded_item_size, (size_t)padded_item_size);
memcpy((void *)list->data + i * padded_item_size, list->data + j * padded_item_size, (size_t)padded_item_size);
@@ -323,8 +326,8 @@ void *List$random(List_t list, OptionalClosure_t random_int64) {
typedef int64_t (*rng_fn_t)(int64_t, int64_t, void *);
rng_fn_t rng_fn = random_int64.fn ? (rng_fn_t)random_int64.fn : _default_random_int64;
- int64_t index = rng_fn(0, list.length - 1, random_int64.userdata);
- if unlikely (index < 0 || index > list.length - 1)
+ int64_t index = rng_fn(0, (int64_t)list.length - 1, random_int64.userdata);
+ if unlikely (index < 0 || index > (int64_t)list.length - 1)
fail("The provided random number function returned an invalid value: ", index, " (not between 0 and ",
(int64_t)list.length, ")");
return list.data + list.stride * index;
@@ -332,9 +335,9 @@ void *List$random(List_t list, OptionalClosure_t random_int64) {
public
Table_t List$counts(List_t list, const TypeInfo_t *type) {
- Table_t counts = {};
+ Table_t counts = EMPTY_TABLE;
const TypeInfo_t count_type = *Table$info(type->ListInfo.item, &Int$info);
- for (int64_t i = 0; i < list.length; i++) {
+ for (int64_t i = 0; i < (int64_t)list.length; i++) {
void *key = list.data + i * list.stride;
int64_t *count = Table$get(counts, key, &count_type);
int64_t val = count ? *count + 1 : 1;
@@ -362,7 +365,7 @@ List_t List$sample(List_t list, Int_t int_n, List_t weights, OptionalClosure_t r
int64_t n = Int64$from_int(int_n, false);
if (n < 0) fail("Cannot select a negative number of values");
- if (n == 0) return (List_t){};
+ if (n == 0) return EMPTY_LIST;
if (list.length == 0) fail("There are no elements in this list!");
@@ -370,7 +373,7 @@ List_t List$sample(List_t list, Int_t int_n, List_t weights, OptionalClosure_t r
fail("List has ", (int64_t)list.length, " elements, but there are ", (int64_t)weights.length, " weights given");
double total = 0.0;
- for (int64_t i = 0; i < weights.length && i < list.length; i++) {
+ for (int64_t i = 0; i < (int64_t)weights.length && i < (int64_t)list.length; i++) {
double weight = *(double *)(weights.data + weights.stride * i);
if (isinf(weight)) fail("Infinite weight!");
else if (isnan(weight)) fail("NaN weight!");
@@ -389,19 +392,19 @@ List_t List$sample(List_t list, Int_t int_n, List_t weights, OptionalClosure_t r
double odds;
} aliases[list.length];
- for (int64_t i = 0; i < list.length; i++) {
- double weight = i >= weights.length ? 0.0 : *(double *)(weights.data + weights.stride * i);
+ for (int64_t i = 0; i < (int64_t)list.length; i++) {
+ double weight = i >= (int64_t)weights.length ? 0.0 : *(double *)(weights.data + weights.stride * i);
aliases[i].odds = weight * inverse_average;
aliases[i].alias = -1;
}
int64_t small = 0;
- for (int64_t big = 0; big < list.length; big++) {
+ for (int64_t big = 0; big < (int64_t)list.length; big++) {
while (aliases[big].odds >= 1.0) {
- while (small < list.length && (aliases[small].odds >= 1.0 || aliases[small].alias != -1))
+ while (small < (int64_t)list.length && (aliases[small].odds >= 1.0 || aliases[small].alias != -1))
++small;
- if (small >= list.length) {
+ if (small >= (int64_t)list.length) {
aliases[big].odds = 1.0;
aliases[big].alias = big;
break;
@@ -413,7 +416,7 @@ List_t List$sample(List_t list, Int_t int_n, List_t weights, OptionalClosure_t r
if (big < small) small = big;
}
- for (int64_t i = small; i < list.length; i++)
+ for (int64_t i = small; i < (int64_t)list.length; i++)
if (aliases[i].alias == -1) aliases[i].alias = i;
typedef double (*rng_fn_t)(void *);
@@ -421,7 +424,7 @@ List_t List$sample(List_t list, Int_t int_n, List_t weights, OptionalClosure_t r
List_t selected = {.data = list.atomic ? GC_MALLOC_ATOMIC((size_t)(n * padded_item_size))
: GC_MALLOC((size_t)(n * padded_item_size)),
- .length = n,
+ .length = (uint64_t)n,
.stride = padded_item_size,
.atomic = list.atomic};
for (int64_t i = 0; i < n; i++) {
@@ -430,7 +433,7 @@ List_t List$sample(List_t list, Int_t int_n, List_t weights, OptionalClosure_t r
fail("The random number function returned a value not between 0.0 (inclusive) and 1.0 (exclusive): ", r);
r *= (double)list.length;
int64_t index = (int64_t)r;
- assert(index >= 0 && index < list.length);
+ assert(index >= 0 && index < (int64_t)list.length);
if ((r - (double)index) > aliases[index].odds) index = aliases[index].alias;
memcpy(selected.data + i * selected.stride, list.data + index * list.stride, (size_t)padded_item_size);
}
@@ -449,29 +452,29 @@ List_t List$by(List_t list, Int_t int_stride, int64_t padded_item_size) {
// In the unlikely event that the stride value would be too large to fit in
// a 15-bit integer, fall back to creating a copy of the list:
if (unlikely(list.stride * stride < LIST_MIN_STRIDE || list.stride * stride > LIST_MAX_STRIDE)) {
- void *copy = NULL;
- int64_t len = (stride < 0 ? list.length / -stride : list.length / stride) + ((list.length % stride) != 0);
- if (len > 0) {
- copy = list.atomic ? GC_MALLOC_ATOMIC((size_t)(len * padded_item_size))
- : GC_MALLOC((size_t)(len * padded_item_size));
- void *start = (stride < 0 ? list.data + (list.stride * (list.length - 1)) : list.data);
- for (int64_t i = 0; i < len; i++)
- memcpy(copy + i * padded_item_size, start + list.stride * stride * i, (size_t)padded_item_size);
- }
+ int64_t len = (stride < 0 ? (int64_t)list.length / -stride : (int64_t)list.length / stride)
+ + (((int64_t)list.length % stride) != 0);
+ if (len <= 0) return list.atomic ? EMPTY_ATOMIC_LIST : EMPTY_LIST;
+ void *copy = list.atomic ? GC_MALLOC_ATOMIC((size_t)(len * padded_item_size))
+ : GC_MALLOC((size_t)(len * padded_item_size));
+ void *start = (stride < 0 ? list.data + (list.stride * ((int64_t)list.length - 1)) : list.data);
+ for (int64_t i = 0; i < len; i++)
+ memcpy(copy + i * padded_item_size, start + list.stride * stride * i, (size_t)padded_item_size);
return (List_t){
.data = copy,
- .length = len,
+ .length = (uint64_t)len,
.stride = padded_item_size,
.atomic = list.atomic,
};
}
- if (stride == 0) return (List_t){.atomic = list.atomic};
+ if (stride == 0) return list.atomic ? EMPTY_ATOMIC_LIST : EMPTY_LIST;
return (List_t){
.atomic = list.atomic,
- .data = (stride < 0 ? list.data + (list.stride * (list.length - 1)) : list.data),
- .length = (stride < 0 ? list.length / -stride : list.length / stride) + ((list.length % stride) != 0),
+ .data = (stride < 0 ? list.data + (list.stride * ((int64_t)list.length - 1)) : list.data),
+ .length = (uint64_t)((stride < 0 ? (int64_t)list.length / -stride : (int64_t)list.length / stride)
+ + (((int64_t)list.length % stride) != 0)),
.stride = list.stride * stride,
.data_refcount = list.data_refcount,
};
@@ -482,19 +485,19 @@ List_t List$slice(List_t list, Int_t int_first, Int_t int_last)
{
int64_t first = Int64$from_int(int_first, false);
- if (first < 0) first = list.length + first + 1;
+ if (first < 0) first = (int64_t)list.length + first + 1;
int64_t last = Int64$from_int(int_last, false);
- if (last < 0) last = list.length + last + 1;
+ if (last < 0) last = (int64_t)list.length + last + 1;
- if (last > list.length) last = list.length;
+ if (last > (int64_t)list.length) last = (int64_t)list.length;
- if (first < 1 || first > list.length || last == 0) return (List_t){.atomic = list.atomic};
+ if (first < 1 || first > (int64_t)list.length || last == 0) return EMPTY_ATOMIC_LIST;
return (List_t){
.atomic = list.atomic,
.data = list.data + list.stride * (first - 1),
- .length = last - first + 1,
+ .length = (uint64_t)(last - first + 1),
.stride = list.stride,
.data_refcount = list.data_refcount,
};
@@ -511,26 +514,26 @@ List_t List$reversed(List_t list, int64_t padded_item_size) {
List_t reversed = list;
reversed.stride = -list.stride;
- reversed.data = list.data + (list.length - 1) * list.stride;
+ reversed.data = list.data + ((int64_t)list.length - 1) * list.stride;
return reversed;
}
public
List_t List$concat(List_t x, List_t y, int64_t padded_item_size) {
- void *data = x.atomic ? GC_MALLOC_ATOMIC((size_t)(padded_item_size * (x.length + y.length)))
- : GC_MALLOC((size_t)(padded_item_size * (x.length + y.length)));
+ void *data = x.atomic ? GC_MALLOC_ATOMIC((size_t)(padded_item_size * (int64_t)(x.length + y.length)))
+ : GC_MALLOC((size_t)(padded_item_size * (int64_t)(x.length + y.length)));
if (x.stride == padded_item_size) {
- memcpy(data, x.data, (size_t)(padded_item_size * x.length));
+ memcpy(data, x.data, (size_t)(padded_item_size * (int64_t)x.length));
} else {
- for (int64_t i = 0; i < x.length; i++)
+ for (int64_t i = 0; i < (int64_t)x.length; i++)
memcpy(data + i * padded_item_size, x.data + i * padded_item_size, (size_t)padded_item_size);
}
- void *dest = data + padded_item_size * x.length;
+ void *dest = data + padded_item_size * (int64_t)x.length;
if (y.stride == padded_item_size) {
- memcpy(dest, y.data, (size_t)(padded_item_size * y.length));
+ memcpy(dest, y.data, (size_t)(padded_item_size * (int64_t)y.length));
} else {
- for (int64_t i = 0; i < y.length; i++)
+ for (int64_t i = 0; i < (int64_t)y.length; i++)
memcpy(dest + i * padded_item_size, y.data + i * y.stride, (size_t)padded_item_size);
}
@@ -545,14 +548,14 @@ List_t List$concat(List_t x, List_t y, int64_t padded_item_size) {
public
bool List$has(List_t list, void *item, const TypeInfo_t *type) {
const TypeInfo_t *item_type = type->ListInfo.item;
- for (int64_t i = 0; i < list.length; i++) {
+ for (int64_t i = 0; i < (int64_t)list.length; i++) {
if (generic_equal(list.data + i * list.stride, item, item_type)) return true;
}
return false;
}
public
-void List$clear(List_t *list) { *list = (List_t){.data = 0, .length = 0}; }
+void List$clear(List_t *list) { *list = list->atomic ? EMPTY_ATOMIC_LIST : EMPTY_LIST; }
public
int32_t List$compare(const void *vx, const void *vy, const TypeInfo_t *type) {
@@ -568,7 +571,8 @@ int32_t List$compare(const void *vx, const void *vy, const TypeInfo_t *type) {
if ((int64_t)x->stride == item_padded_size && (int64_t)y->stride == item_padded_size
&& item->size == item_padded_size) {
- int32_t cmp = (int32_t)memcmp(x->data, y->data, (size_t)(MIN(x->length, y->length) * item_padded_size));
+ int32_t cmp = (int32_t)memcmp(x->data, y->data,
+ (size_t)(MIN((int64_t)x->length, (int64_t)y->length) * item_padded_size));
if (cmp != 0) return cmp;
} else {
for (int32_t i = 0, len = MIN(x->length, y->length); i < len; i++) {
@@ -597,7 +601,7 @@ Text_t List$as_text(const void *obj, bool colorize, const TypeInfo_t *type) {
const TypeInfo_t *item_type = type->ListInfo.item;
Text_t text = Text("[");
- for (int64_t i = 0; i < list->length; i++) {
+ for (int64_t i = 0; i < (int64_t)list->length; i++) {
if (i > 0) text = Text$concat(text, Text(", "));
Text_t item_text = generic_as_text(list->data + i * list->stride, colorize, item_type);
text = Text$concat(text, item_text);
@@ -613,10 +617,10 @@ uint64_t List$hash(const void *obj, const TypeInfo_t *type) {
siphash sh;
siphashinit(&sh, sizeof(uint64_t[list->length]));
if (item->tag == PointerInfo || (!item->metamethods.hash && item->size == sizeof(void *))) { // Raw data hash
- for (int64_t i = 0; i < list->length; i++)
+ for (int64_t i = 0; i < (int64_t)list->length; i++)
siphashadd64bits(&sh, (uint64_t)(list->data + i * list->stride));
} else {
- for (int64_t i = 0; i < list->length; i++) {
+ for (int64_t i = 0; i < (int64_t)list->length; i++) {
uint64_t item_hash = generic_hash(list->data + i * list->stride, item);
siphashadd64bits(&sh, item_hash);
}
@@ -625,7 +629,7 @@ uint64_t List$hash(const void *obj, const TypeInfo_t *type) {
}
static void siftdown(List_t *heap, int64_t startpos, int64_t pos, Closure_t comparison, int64_t padded_item_size) {
- assert(pos > 0 && pos < heap->length);
+ assert(pos > 0 && pos < (int64_t)heap->length);
char newitem[padded_item_size];
memcpy(newitem, heap->data + heap->stride * pos, (size_t)(padded_item_size));
while (pos > startpos) {
@@ -641,7 +645,7 @@ static void siftdown(List_t *heap, int64_t startpos, int64_t pos, Closure_t comp
}
static void siftup(List_t *heap, int64_t pos, Closure_t comparison, int64_t padded_item_size) {
- int64_t endpos = heap->length;
+ int64_t endpos = (int64_t)heap->length;
int64_t startpos = pos;
assert(pos < endpos);
@@ -673,7 +677,7 @@ void List$heap_push(List_t *heap, const void *item, Closure_t comparison, int64_
if (heap->length > 1) {
if (heap->data_refcount != 0) List$compact(heap, padded_item_size);
- siftdown(heap, 0, heap->length - 1, comparison, padded_item_size);
+ siftdown(heap, 0, (int64_t)heap->length - 1, comparison, padded_item_size);
}
}
@@ -682,13 +686,13 @@ void List$heap_pop(List_t *heap, Closure_t comparison, int64_t padded_item_size)
if (heap->length == 0) fail("Attempt to pop from an empty list");
if (heap->length == 1) {
- *heap = (List_t){};
+ *heap = EMPTY_LIST;
} else if (heap->length == 2) {
heap->data += heap->stride;
--heap->length;
} else {
if (heap->data_refcount != 0) List$compact(heap, padded_item_size);
- memcpy(heap->data, heap->data + heap->stride * (heap->length - 1), (size_t)(padded_item_size));
+ memcpy(heap->data, heap->data + heap->stride * ((int64_t)heap->length - 1), (size_t)(padded_item_size));
--heap->length;
siftup(heap, 0, comparison, padded_item_size);
}
@@ -701,7 +705,7 @@ void List$heapify(List_t *heap, Closure_t comparison, int64_t padded_item_size)
// It's necessary to bump the refcount because the user's comparison
// function could do stuff that modifies the heap's data.
LIST_INCREF(*heap);
- int64_t i, n = heap->length;
+ int64_t i, n = (int64_t)heap->length;
for (i = (n >> 1) - 1; i >= 0; i--)
siftup(heap, i, comparison, padded_item_size);
LIST_DECREF(*heap);
@@ -710,7 +714,7 @@ void List$heapify(List_t *heap, Closure_t comparison, int64_t padded_item_size)
public
Int_t List$binary_search(List_t list, void *target, Closure_t comparison) {
typedef int32_t (*cmp_fn_t)(void *, void *, void *);
- int64_t lo = 0, hi = list.length - 1;
+ int64_t lo = 0, hi = (int64_t)list.length - 1;
while (lo <= hi) {
int64_t mid = (lo + hi) / 2;
int32_t cmp = ((cmp_fn_t)comparison.fn)(list.data + list.stride * mid, target, comparison.userdata);
@@ -724,13 +728,13 @@ Int_t List$binary_search(List_t list, void *target, Closure_t comparison) {
public
PUREFUNC bool List$is_none(const void *obj, const TypeInfo_t *info) {
(void)info;
- return ((List_t *)obj)->length < 0;
+ return ((List_t *)obj)->data == NULL;
}
public
void List$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) {
List_t list = *(List_t *)obj;
- int64_t len = list.length;
+ int64_t len = (int64_t)list.length;
Int64$serialize(&len, out, pointers, &Int64$info);
serialize_fn_t item_serialize = type->ListInfo.item->metamethods.serialize;
if (item_serialize) {
@@ -752,7 +756,7 @@ void List$deserialize(FILE *in, void *obj, List_t *pointers, const TypeInfo_t *t
if (type->ListInfo.item->align > 0 && padded_size % type->ListInfo.item->align > 0)
padded_size += type->ListInfo.item->align - (padded_size % type->ListInfo.item->align);
List_t list = {
- .length = len,
+ .length = (uint64_t)len,
.data = GC_MALLOC((size_t)(len * padded_size)),
.stride = padded_size,
};
diff --git a/src/stdlib/lists.h b/src/stdlib/lists.h
index 1386b2fa..457fed52 100644
--- a/src/stdlib/lists.h
+++ b/src/stdlib/lists.h
@@ -9,6 +9,10 @@
#include "types.h"
#include "util.h"
+extern char _EMPTY_LIST_SENTINEL;
+#define EMPTY_LIST ((List_t){.data = &_EMPTY_LIST_SENTINEL})
+#define EMPTY_ATOMIC_LIST ((List_t){.data = &_EMPTY_LIST_SENTINEL, .atomic = 1})
+
// Convert negative indices to back-indexed without branching: index0 = index + (index < 0)*(len+1)) - 1
#define List_get_checked(list_expr, index_expr, item_type, start, end) \
({ \
diff --git a/src/stdlib/metamethods.c b/src/stdlib/metamethods.c
index 6161918c..3eff2dd3 100644
--- a/src/stdlib/metamethods.c
+++ b/src/stdlib/metamethods.c
@@ -6,6 +6,7 @@
#include "lists.h"
#include "metamethods.h"
#include "siphash.h"
+#include "tables.h"
#include "types.h"
#include "util.h"
@@ -50,12 +51,12 @@ List_t generic_serialize(const void *x, const TypeInfo_t *type) {
char *buf = NULL;
size_t size = 0;
FILE *stream = open_memstream(&buf, &size);
- Table_t pointers = {};
+ Table_t pointers = EMPTY_TABLE;
_serialize(x, stream, &pointers, type);
fclose(stream);
List_t bytes = {
.data = GC_MALLOC_ATOMIC(size),
- .length = (int64_t)size,
+ .length = (uint64_t)size,
.stride = 1,
.atomic = 1,
};
@@ -79,7 +80,7 @@ void generic_deserialize(List_t bytes, void *outval, const TypeInfo_t *type) {
if (bytes.stride != 1) List$compact(&bytes, 1);
FILE *input = fmemopen(bytes.data, (size_t)bytes.length, "r");
- List_t pointers = {};
+ List_t pointers = EMPTY_LIST;
_deserialize(input, outval, &pointers, type);
fclose(input);
}
diff --git a/src/stdlib/optionals.c b/src/stdlib/optionals.c
index e9184e4d..3fe812b1 100644
--- a/src/stdlib/optionals.c
+++ b/src/stdlib/optionals.c
@@ -13,8 +13,8 @@ public
PUREFUNC bool is_none(const void *obj, const TypeInfo_t *non_optional_type) {
if (non_optional_type->metamethods.is_none) return non_optional_type->metamethods.is_none(obj, non_optional_type);
- const void *dest = (obj + non_optional_type->size);
- return *(bool *)dest;
+ const bool *has_value = (const bool *)(obj + non_optional_type->size);
+ return !(*has_value);
}
PUREFUNC public uint64_t Optional$hash(const void *obj, const TypeInfo_t *type) {
@@ -64,8 +64,8 @@ void Optional$deserialize(FILE *in, void *outval, List_t *pointers, const TypeIn
_deserialize(in, outval, pointers, nonnull);
} else {
if (nonnull->tag == TextInfo) *(Text_t *)outval = NONE_TEXT;
- else if (nonnull->tag == ListInfo) *(List_t *)outval = (List_t){.length = -1};
- else if (nonnull->tag == TableInfo) *(Table_t *)outval = (Table_t){.entries = {.length = -1}};
+ else if (nonnull->tag == ListInfo) *(List_t *)outval = NONE_LIST;
+ else if (nonnull->tag == TableInfo) *(Table_t *)outval = NONE_TABLE;
else if (nonnull == &Num$info) *(double *)outval = (double)NAN;
else if (nonnull == &Num32$info) *(float *)outval = (float)NAN;
else if (nonnull->tag == StructInfo || (nonnull->tag == OpaqueInfo && type->size > nonnull->size))
diff --git a/src/stdlib/optionals.h b/src/stdlib/optionals.h
index 145fda60..9c875bd1 100644
--- a/src/stdlib/optionals.h
+++ b/src/stdlib/optionals.h
@@ -9,12 +9,12 @@
#include "types.h"
#include "util.h"
-#define NONE_LIST ((List_t){.length = -1})
+#define NONE_LIST ((List_t){.data = NULL})
#define NONE_BOOL ((OptionalBool_t)2)
#define NONE_INT ((OptionalInt_t){.small = 0})
-#define NONE_TABLE ((OptionalTable_t){.entries.length = -1})
+#define NONE_TABLE ((OptionalTable_t){.entries.data = NULL})
#define NONE_CLOSURE ((OptionalClosure_t){.fn = NULL})
-#define NONE_TEXT ((OptionalText_t){.length = -1})
+#define NONE_TEXT ((OptionalText_t){.tag = TEXT_NONE})
#define NONE_PATH ((Path_t){.type = PATH_NONE})
PUREFUNC bool is_none(const void *obj, const TypeInfo_t *non_optional_type);
diff --git a/src/stdlib/paths.c b/src/stdlib/paths.c
index cd7a9c6d..ee85d5bb 100644
--- a/src/stdlib/paths.c
+++ b/src/stdlib/paths.c
@@ -36,7 +36,7 @@ static const Path_t HOME_PATH = {.type.$tag = PATH_HOME}, ROOT_PATH = {.type.$ta
CURDIR_PATH = {.type.$tag = PATH_RELATIVE};
static void clean_components(List_t *components) {
- for (int64_t i = 0; i < components->length;) {
+ for (int64_t i = 0; i < (int64_t)components->length;) {
Text_t *component = (Text_t *)(components->data + i * components->stride);
if (component->length == 0 || Text$equal_values(*component, Text("."))) {
List$remove_at(components, I(i + 1), I(1), sizeof(Text_t));
@@ -83,10 +83,11 @@ Path_t Path$from_str(const char *str) {
// ignore /./
} else if (component_len == 2 && strncmp(str, "..", 2) == 0 && result.components.length > 1
&& !Text$equal_values(
- Text(".."), *(Text_t *)(result.components.data
- + result.components.stride * (result.components.length - 1)))) {
+ Text(".."),
+ *(Text_t *)(result.components.data
+ + result.components.stride * ((int64_t)result.components.length - 1)))) {
// Pop off /foo/baz/.. -> /foo
- List$remove_at(&result.components, I(result.components.length), I(1), sizeof(Text_t));
+ List$remove_at(&result.components, I((int64_t)result.components.length), I(1), sizeof(Text_t));
} else {
Text_t component = Text$from_strn(str, component_len);
List$insert_value(&result.components, component, I(0), sizeof(Text_t));
@@ -149,16 +150,16 @@ Path_t Path$relative_to(Path_t path, Path_t relative_to) {
Path_t result = {.type.$tag = PATH_RELATIVE};
int64_t shared = 0;
- for (; shared < path.components.length && shared < relative_to.components.length; shared++) {
+ for (; shared < (int64_t)path.components.length && shared < (int64_t)relative_to.components.length; shared++) {
Text_t *p = (Text_t *)(path.components.data + shared * path.components.stride);
Text_t *r = (Text_t *)(relative_to.components.data + shared * relative_to.components.stride);
if (!Text$equal_values(*p, *r)) break;
}
- for (int64_t i = shared; i < relative_to.components.length; i++)
+ for (int64_t i = shared; i < (int64_t)relative_to.components.length; i++)
List$insert_value(&result.components, Text(".."), I(1), sizeof(Text_t));
- for (int64_t i = shared; i < path.components.length; i++) {
+ for (int64_t i = shared; i < (int64_t)path.components.length; i++) {
Text_t *p = (Text_t *)(path.components.data + i * path.components.stride);
List$insert(&result.components, p, I(0), sizeof(Text_t));
}
@@ -348,7 +349,7 @@ OptionalList_t Path$read_bytes(Path_t path, OptionalInt_t count) {
if (count.small && (int64_t)sb.st_size < target_count)
fail("Could not read ", target_count, " bytes from ", path, " (only got ", (uint64_t)sb.st_size, ")");
int64_t len = count.small ? target_count : (int64_t)sb.st_size;
- return (List_t){.data = content, .atomic = 1, .stride = 1, .length = len};
+ return (List_t){.data = content, .atomic = 1, .stride = 1, .length = (uint64_t)len};
} else {
size_t capacity = 256, len = 0;
char *content = GC_MALLOC_ATOMIC(capacity);
@@ -376,14 +377,14 @@ OptionalList_t Path$read_bytes(Path_t path, OptionalInt_t count) {
close(fd);
if (count.small != 0 && (int64_t)len < target_count)
fail("Could not read ", target_count, " bytes from ", path, " (only got ", (uint64_t)len, ")");
- return (List_t){.data = content, .atomic = 1, .stride = 1, .length = (int64_t)len};
+ return (List_t){.data = content, .atomic = 1, .stride = 1, .length = (uint64_t)len};
}
}
public
OptionalText_t Path$read(Path_t path) {
List_t bytes = Path$read_bytes(path, NONE_INT);
- if (bytes.length < 0) return NONE_TEXT;
+ if (bytes.data == NULL) return NONE_TEXT;
return Text$from_utf8(bytes);
}
@@ -408,14 +409,14 @@ OptionalText_t Path$group(Path_t path, bool follow_symlinks) {
public
void Path$set_owner(Path_t path, OptionalText_t owner, OptionalText_t group, bool follow_symlinks) {
uid_t owner_id = (uid_t)-1;
- if (owner.length >= 0) {
+ if (owner.tag == TEXT_NONE) {
struct passwd *pwd = getpwnam(Text$as_c_string(owner));
if (pwd == NULL) fail("Not a valid user: ", owner);
owner_id = pwd->pw_uid;
}
gid_t group_id = (gid_t)-1;
- if (group.length >= 0) {
+ if (group.tag == TEXT_NONE) {
struct group *grp = getgrnam(Text$as_c_string(group));
if (grp == NULL) fail("Not a valid group: ", group);
group_id = grp->gr_gid;
@@ -476,7 +477,7 @@ void Path$create_directory(Path_t path, int permissions) {
static List_t _filtered_children(Path_t path, bool include_hidden, mode_t filter) {
path = Path$expand_home(path);
struct dirent *dir;
- List_t children = {};
+ List_t children = EMPTY_LIST;
const char *path_str = Path$as_c_string(path);
size_t path_len = strlen(path_str);
DIR *d = opendir(path_str);
@@ -562,7 +563,7 @@ Path_t Path$parent(Path_t path) {
return path;
} else if (path.components.length > 0
&& !Text$equal_values(
- *(Text_t *)(path.components.data + path.components.stride * (path.components.length - 1)),
+ *(Text_t *)(path.components.data + path.components.stride * ((int64_t)path.components.length - 1)),
Text(".."))) {
return (Path_t){.type.$tag = path.type.$tag, .components = List$slice(path.components, I(1), I(-2))};
} else {
@@ -576,7 +577,7 @@ Path_t Path$parent(Path_t path) {
public
PUREFUNC Text_t Path$base_name(Path_t path) {
if (path.components.length >= 1)
- return *(Text_t *)(path.components.data + path.components.stride * (path.components.length - 1));
+ return *(Text_t *)(path.components.data + path.components.stride * ((int64_t)path.components.length - 1));
else if (path.type.$tag == PATH_HOME) return Text("~");
else if (path.type.$tag == PATH_RELATIVE) return Text(".");
else return EMPTY_TEXT;
@@ -594,7 +595,7 @@ public
bool Path$has_extension(Path_t path, Text_t extension) {
if (path.components.length < 2) return extension.length == 0;
- Text_t last = *(Text_t *)(path.components.data + path.components.stride * (path.components.length - 1));
+ Text_t last = *(Text_t *)(path.components.data + path.components.stride * ((int64_t)path.components.length - 1));
if (extension.length == 0)
return !Text$has(Text$from(last, I(2)), Text(".")) || Text$equal_values(last, Text(".."));
@@ -632,7 +633,7 @@ Path_t Path$with_extension(Path_t path, Text_t extension, bool replace) {
.components = path.components,
};
LIST_INCREF(result.components);
- Text_t last = *(Text_t *)(path.components.data + path.components.stride * (path.components.length - 1));
+ Text_t last = *(Text_t *)(path.components.data + path.components.stride * ((int64_t)path.components.length - 1));
List$remove_at(&result.components, I(-1), I(1), sizeof(Text_t));
if (replace) {
const char *base = Text$as_c_string(last);
@@ -701,7 +702,7 @@ List_t Path$glob(Path_t path) {
int status = glob(Path$as_c_string(path), GLOB_BRACE | GLOB_TILDE, NULL, &glob_result);
if (status != 0 && status != GLOB_NOMATCH) fail("Failed to perform globbing");
- List_t glob_files = {};
+ List_t glob_files = EMPTY_LIST;
for (size_t i = 0; i < glob_result.gl_pathc; i++) {
size_t len = strlen(glob_result.gl_pathv[i]);
if ((len >= 2 && glob_result.gl_pathv[i][len - 1] == '.' && glob_result.gl_pathv[i][len - 2] == '/')
@@ -727,7 +728,7 @@ PUREFUNC uint64_t Path$hash(const void *obj, const TypeInfo_t *type) {
Path_t *path = (Path_t *)obj;
siphash sh;
siphashinit(&sh, (uint64_t)path->type.$tag);
- for (int64_t i = 0; i < path->components.length; i++) {
+ for (int64_t i = 0; i < (int64_t)path->components.length; i++) {
uint64_t item_hash = Text$hash(path->components.data + i * path->components.stride, &Text$info);
siphashadd64bits(&sh, item_hash);
}
@@ -774,10 +775,10 @@ int Path$print(FILE *f, Path_t path) {
if (!Text$equal_values(*(Text_t *)path.components.data, Text(".."))) n += fputs("./", f);
}
- for (int64_t i = 0; i < path.components.length; i++) {
+ for (int64_t i = 0; i < (int64_t)path.components.length; i++) {
Text_t *comp = (Text_t *)(path.components.data + i * path.components.stride);
n += Text$print(f, *comp);
- if (i + 1 < path.components.length) n += fputc('/', f);
+ if (i + 1 < (int64_t)path.components.length) n += fputc('/', f);
}
return n;
}
diff --git a/src/stdlib/pointers.c b/src/stdlib/pointers.c
index 0a1623a0..74037613 100644
--- a/src/stdlib/pointers.c
+++ b/src/stdlib/pointers.c
@@ -30,7 +30,7 @@ Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo_t *type) {
}
static const void *root = NULL;
- static Table_t pending = {};
+ static Table_t pending = EMPTY_TABLE;
bool top_level = (root == NULL);
// Check for recursive references, so if `x.foo = x`, then it prints as
@@ -47,7 +47,7 @@ Text_t Pointer$as_text(const void *x, bool colorize, const TypeInfo_t *type) {
Text_t text = Texts(Text$from_str(ptr_info.sigil), Int64$value_as_text(*id));
return colorize ? Texts(Text("\x1b[34;1m"), text, Text("\x1b[m")) : text;
}
- int64_t next_id = pending.entries.length + 2;
+ int64_t next_id = (int64_t)pending.entries.length + 2;
Table$set(&pending, x, &next_id, &rec_table);
}
@@ -97,7 +97,7 @@ void Pointer$serialize(const void *obj, FILE *out, Table_t *pointers, const Type
if (id_ptr) {
id = *id_ptr;
} else {
- id = pointers->entries.length + 1;
+ id = (int64_t)pointers->entries.length + 1;
Table$set(pointers, &ptr, &id, &ptr_to_int_table);
}
@@ -112,7 +112,7 @@ void Pointer$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInf
Int64$deserialize(in, &id, pointers, &Int64$info);
assert(id != 0);
- if (id > pointers->length) {
+ if (id > (int64_t)pointers->length) {
void *obj = GC_MALLOC((size_t)type->PointerInfo.pointed->size);
List$insert(pointers, &obj, I(0), sizeof(void *));
_deserialize(in, obj, pointers, type->PointerInfo.pointed);
diff --git a/src/stdlib/tables.c b/src/stdlib/tables.c
index 6698dea3..c093e4c2 100644
--- a/src/stdlib/tables.c
+++ b/src/stdlib/tables.c
@@ -187,7 +187,7 @@ static void hashmap_resize_buckets(Table_t *t, uint32_t new_capacity, const Type
t->bucket_info->count = new_capacity;
t->bucket_info->last_free = new_capacity - 1;
// Rehash:
- for (int64_t i = 0; i < Table$length(*t); i++) {
+ for (int64_t i = 0; i < (int64_t)Table$length(*t); i++) {
hdebug("Rehashing ", i, "\n");
Table$set_bucket(t, GET_ENTRY(*t, i), i, type);
}
@@ -252,7 +252,7 @@ void *Table$reserve(Table_t *t, const void *key, const void *value, const TypeIn
else if (value_size > 0) memset(buf + value_offset(type), 0, (size_t)value_size);
List$insert(&t->entries, buf, I(0), (int64_t)entry_size(type));
- int64_t entry_index = t->entries.length - 1;
+ int64_t entry_index = (int64_t)t->entries.length - 1;
void *entry = GET_ENTRY(*t, entry_index);
Table$set_bucket(t, entry, entry_index, type);
return entry + value_offset(type);
@@ -276,7 +276,7 @@ void Table$remove(Table_t *t, const void *key, const TypeInfo_t *type) {
maybe_copy_on_write(t, type);
// If unspecified, pop the last key:
- if (!key) key = GET_ENTRY(*t, t->entries.length - 1);
+ if (!key) key = GET_ENTRY(*t, (int64_t)t->entries.length - 1);
// Steps: look up the bucket for the removed key
// If missing, then return immediately
@@ -316,7 +316,7 @@ found_it:;
// swap the other entry into the last position and then remove the last
// entry. This disturbs the ordering of the table, but keeps removal O(1)
// instead of O(N)
- int64_t last_entry = t->entries.length - 1;
+ int64_t last_entry = (int64_t)t->entries.length - 1;
if (bucket->index != last_entry) {
hdebug("Removing key/value from the middle of the entries list\n");
@@ -336,7 +336,7 @@ found_it:;
// Last entry is being removed, so clear it out to be safe:
memset(GET_ENTRY(*t, last_entry), 0, entry_size(type));
- List$remove_at(&t->entries, I(t->entries.length), I(1), (int64_t)entry_size(type));
+ List$remove_at(&t->entries, I((int64_t)t->entries.length), I(1), (int64_t)entry_size(type));
int64_t bucket_to_clear;
if (prev) { // Middle (or end) of a chain
@@ -359,7 +359,7 @@ found_it:;
}
CONSTFUNC public void *Table$entry(Table_t t, int64_t n) {
- if (n < 1 || n > Table$length(t)) return NULL;
+ if (n < 1 || n > (int64_t)Table$length(t)) return NULL;
return GET_ENTRY(t, n - 1);
}
@@ -386,7 +386,7 @@ PUREFUNC public bool Table$equal(const void *vx, const void *vy, const TypeInfo_
const TypeInfo_t *value_type = type->TableInfo.value;
size_t offset = value_offset(type);
- for (int64_t i = 0; i < x->entries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)x->entries.length; i++) {
void *x_key = x->entries.data + i * x->entries.stride;
void *y_value = Table$get_raw(*y, x_key, type);
if (!y_value) return false;
@@ -418,7 +418,7 @@ PUREFUNC public int32_t Table$compare(const void *vx, const void *vy, const Type
// `x[k] != y[k]`, as well as the largest key in `x` and `y`.
void *mismatched_key = NULL, *max_x_key = NULL;
- for (int64_t i = 0; i < x->entries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)x->entries.length; i++) {
void *key = x->entries.data + x->entries.stride * i;
if (max_x_key == NULL || generic_compare(key, max_x_key, table.key) > 0) max_x_key = key;
@@ -433,7 +433,7 @@ PUREFUNC public int32_t Table$compare(const void *vx, const void *vy, const Type
// If the keys are not all equal, we gotta check to see if there exists a
// `y[k]` such that `k` is smaller than all keys that `x` has and `y` doesn't:
void *max_y_key = NULL;
- for (int64_t i = 0; i < y->entries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)y->entries.length; i++) {
void *key = y->entries.data + y->entries.stride * i;
if (max_y_key == NULL || generic_compare(key, max_y_key, table.key) > 0) max_y_key = key;
@@ -474,7 +474,7 @@ PUREFUNC public int32_t Table$compare(const void *vx, const void *vy, const Type
// Assuming keys are the same, compare values:
if (table.value->size > 0) {
- for (int64_t i = 0; i < x->entries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)x->entries.length; i++) {
void *key = x->entries.data + x->entries.stride * i;
void *x_value = key + value_offset(type);
void *y_value = Table$get_raw(*y, key, type);
@@ -504,12 +504,12 @@ PUREFUNC public uint64_t Table$hash(const void *obj, const TypeInfo_t *type) {
uint64_t keys_hash = 0, values_hash = 0;
size_t offset = value_offset(type);
if (table.value->size > 0) {
- for (int64_t i = 0; i < t->entries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)t->entries.length; i++) {
keys_hash ^= generic_hash(t->entries.data + i * t->entries.stride, table.key);
values_hash ^= generic_hash(t->entries.data + i * t->entries.stride + offset, table.value);
}
} else {
- for (int64_t i = 0; i < t->entries.length; i++)
+ for (int64_t i = 0; i < (int64_t)t->entries.length; i++)
keys_hash ^= generic_hash(t->entries.data + i * t->entries.stride, table.key);
}
@@ -517,7 +517,7 @@ PUREFUNC public uint64_t Table$hash(const void *obj, const TypeInfo_t *type) {
int64_t length;
uint64_t keys_hash, values_hash, fallback_hash;
} components = {
- t->entries.length,
+ (int64_t)t->entries.length,
keys_hash,
values_hash,
t->fallback ? Table$hash(t->fallback, type) : 0,
@@ -540,7 +540,7 @@ Text_t Table$as_text(const void *obj, bool colorize, const TypeInfo_t *type) {
int64_t val_off = (int64_t)value_offset(type);
Text_t text = Text("{");
- for (int64_t i = 0, length = Table$length(*t); i < length; i++) {
+ for (int64_t i = 0, length = (int64_t)Table$length(*t); i < length; i++) {
if (i > 0) text = Text$concat(text, Text(", "));
void *entry = GET_ENTRY(*t, i);
text = Text$concat(text, generic_as_text(entry, colorize, table.key));
@@ -561,8 +561,8 @@ Table_t Table$from_entries(List_t entries, const TypeInfo_t *type) {
assert(type->tag == TableInfo);
if (entries.length == 0) return (Table_t){};
- Table_t t = {};
- int64_t length = entries.length + entries.length / 4;
+ Table_t t = EMPTY_TABLE;
+ int64_t length = (int64_t)entries.length + (int64_t)entries.length / 4;
size_t alloc_size = sizeof(bucket_info_t) + sizeof(bucket_t[length]);
t.bucket_info = GC_MALLOC_ATOMIC(alloc_size);
memset(t.bucket_info->buckets, 0, sizeof(bucket_t[length]));
@@ -570,7 +570,7 @@ Table_t Table$from_entries(List_t entries, const TypeInfo_t *type) {
t.bucket_info->last_free = length - 1;
size_t offset = value_offset(type);
- for (int64_t i = 0; i < entries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)entries.length; i++) {
void *key = entries.data + i * entries.stride;
Table$set(&t, key, key + offset, type);
}
@@ -581,10 +581,10 @@ Table_t Table$from_entries(List_t entries, const TypeInfo_t *type) {
public
Table_t Table$intersection(Table_t a, Table_t b, const TypeInfo_t *type) {
// Return a table such that t[k]==a[k] for all k such that a.has(k), b.has(k), and a[k]==b[k]
- Table_t result = {};
+ Table_t result = EMPTY_TABLE;
const size_t offset = value_offset(type);
for (Table_t *t = &a; t; t = t->fallback) {
- for (int64_t i = 0; i < Table$length(*t); i++) {
+ for (int64_t i = 0; i < (int64_t)Table$length(*t); i++) {
void *key = GET_ENTRY(*t, i);
void *a_value = key + offset;
void *b_value = Table$get(b, key, type);
@@ -600,16 +600,16 @@ public
Table_t Table$with(Table_t a, Table_t b, const TypeInfo_t *type) {
// return a table such that t[k]==b[k] for all k such that b.has(k), and t[k]==a[k] for all k such that a.has(k) and
// not b.has(k)
- Table_t result = {};
+ Table_t result = EMPTY_TABLE;
const size_t offset = value_offset(type);
for (Table_t *t = &a; t; t = t->fallback) {
- for (int64_t i = 0; i < Table$length(*t); i++) {
+ for (int64_t i = 0; i < (int64_t)Table$length(*t); i++) {
void *key = GET_ENTRY(*t, i);
Table$set(&result, key, key + offset, type);
}
}
for (Table_t *t = &b; t; t = t->fallback) {
- for (int64_t i = 0; i < Table$length(*t); i++) {
+ for (int64_t i = 0; i < (int64_t)Table$length(*t); i++) {
void *key = GET_ENTRY(*t, i);
Table$set(&result, key, key + offset, type);
}
@@ -621,16 +621,16 @@ Table_t Table$with(Table_t a, Table_t b, const TypeInfo_t *type) {
public
Table_t Table$difference(Table_t a, Table_t b, const TypeInfo_t *type) {
// return a table with elements in `a` or `b`, but not both
- Table_t result = {};
+ Table_t result = EMPTY_TABLE;
const size_t offset = value_offset(type);
for (Table_t *t = &a; t; t = t->fallback) {
- for (int64_t i = 0; i < Table$length(*t); i++) {
+ for (int64_t i = 0; i < (int64_t)Table$length(*t); i++) {
void *key = GET_ENTRY(*t, i);
if (Table$get(b, key, type) == NULL) Table$set(&result, key, key + offset, type);
}
}
for (Table_t *t = &b; t; t = t->fallback) {
- for (int64_t i = 0; i < Table$length(*t); i++) {
+ for (int64_t i = 0; i < (int64_t)Table$length(*t); i++) {
void *key = GET_ENTRY(*t, i);
if (Table$get(a, key, type) == NULL) Table$set(&result, key, key + offset, type);
}
@@ -642,10 +642,10 @@ Table_t Table$difference(Table_t a, Table_t b, const TypeInfo_t *type) {
public
Table_t Table$without(Table_t a, Table_t b, const TypeInfo_t *type) {
// Return a table such that t[k]==a[k] for all k such that not b.has(k) or b[k] != a[k]
- Table_t result = {};
+ Table_t result = EMPTY_TABLE;
const size_t offset = value_offset(type);
for (Table_t *t = &a; t; t = t->fallback) {
- for (int64_t i = 0; i < Table$length(*t); i++) {
+ for (int64_t i = 0; i < (int64_t)Table$length(*t); i++) {
void *key = GET_ENTRY(*t, i);
void *a_value = key + offset;
void *b_value = Table$get(b, key, type);
@@ -672,7 +672,7 @@ Table_t Table$with_fallback(Table_t t, OptionalTable_t fallback) {
PUREFUNC public bool Table$is_subset_of(Table_t a, Table_t b, bool strict, const TypeInfo_t *type) {
if (a.entries.length > b.entries.length || (strict && a.entries.length == b.entries.length)) return false;
- for (int64_t i = 0; i < Table$length(a); i++) {
+ for (int64_t i = 0; i < (int64_t)Table$length(a); i++) {
void *found = Table$get_raw(b, GET_ENTRY(a, i), type);
if (!found) return false;
}
@@ -708,13 +708,13 @@ CONSTFUNC public void *Table$str_entry(Table_t t, int64_t n) { return Table$entr
PUREFUNC public bool Table$is_none(const void *obj, const TypeInfo_t *info) {
(void)info;
- return ((Table_t *)obj)->entries.length < 0;
+ return ((Table_t *)obj)->entries.data == NULL;
}
public
void Table$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) {
Table_t *t = (Table_t *)obj;
- int64_t len = t->entries.length;
+ int64_t len = (int64_t)t->entries.length;
Int64$serialize(&len, out, pointers, &Int64$info);
size_t offset = value_offset(type);
@@ -737,7 +737,7 @@ void Table$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_
int64_t len;
Int64$deserialize(in, &len, pointers, &Int$info);
- Table_t t = {};
+ Table_t t = EMPTY_TABLE;
for (int64_t i = 0; i < len; i++) {
char key[type->TableInfo.key->size];
_deserialize(in, key, pointers, type->TableInfo.key);
diff --git a/src/stdlib/tables.h b/src/stdlib/tables.h
index f4870f80..cc2b3b91 100644
--- a/src/stdlib/tables.h
+++ b/src/stdlib/tables.h
@@ -11,6 +11,8 @@
#include "types.h"
#include "util.h"
+#define EMPTY_TABLE ((Table_t){.entries.data = &_EMPTY_LIST_SENTINEL})
+
#define Table(key_t, val_t, key_info, value_info, fb, N, ...) \
({ \
struct { \
diff --git a/src/stdlib/text.c b/src/stdlib/text.c
index cda7dd31..0f40aef9 100644
--- a/src/stdlib/text.c
+++ b/src/stdlib/text.c
@@ -127,7 +127,7 @@ typedef struct {
} synthetic_grapheme_t;
// Synthetic grapheme clusters (clusters of more than one codepoint):
-static Table_t grapheme_ids_by_codepoints = {}; // ucs4_t* length-prefixed codepoints -> int32_t ID
+static Table_t grapheme_ids_by_codepoints = EMPTY_TABLE; // ucs4_t* length-prefixed codepoints -> int32_t ID
// This will hold a dynamically growing list of synthetic graphemes:
static synthetic_grapheme_t *synthetic_graphemes = NULL;
@@ -521,8 +521,7 @@ static Text_t concat2(Text_t a, Text_t b) {
}
OptionalText_t glue =
- Text$from_utf32((List_t){.data = normalized, .length = (int64_t)norm_length, .stride = sizeof(ucs4_t)});
- assert(glue.length >= 0);
+ Text$from_utf32((List_t){.data = normalized, .length = (uint64_t)norm_length, .stride = sizeof(ucs4_t)});
if (normalized != norm_buf) free(normalized);
@@ -743,14 +742,14 @@ static Text_t Text$from_components(List_t graphemes, Table_t unique_clusters) {
void *blob = GC_MALLOC_ATOMIC(blob_size);
int32_t *map = blob;
uint8_t *bytes = blob + sizeof(int32_t[unique_clusters.entries.length]);
- for (int64_t i = 0; i < unique_clusters.entries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)unique_clusters.entries.length; i++) {
struct {
int32_t g;
uint8_t b;
} *entry = unique_clusters.entries.data + i * unique_clusters.entries.stride;
map[entry->b] = entry->g;
}
- for (int64_t i = 0; i < graphemes.length; i++) {
+ for (int64_t i = 0; i < (int64_t)graphemes.length; i++) {
int32_t g = *(int32_t *)(graphemes.data + i * graphemes.stride);
uint8_t *byte = Table$get(unique_clusters, &g, Table$info(&Int32$info, &Byte$info));
assert(byte);
@@ -785,8 +784,8 @@ OptionalText_t Text$from_strn(const char *str, size_t len) {
}
if (u8_check((uint8_t *)str, len) != NULL) return NONE_TEXT;
- List_t graphemes = {};
- Table_t unique_clusters = {};
+ List_t graphemes = EMPTY_LIST;
+ Table_t unique_clusters = EMPTY_TABLE;
const uint8_t *pos = (const uint8_t *)str;
const uint8_t *end = (const uint8_t *)&str[len];
// Iterate over grapheme clusters
@@ -1138,7 +1137,7 @@ Text_t Text$translate(Text_t text, Table_t translations) {
int64_t span_start = 0;
List_t replacement_list = translations.entries;
for (int64_t i = 0; i < text.length;) {
- for (int64_t r = 0; r < replacement_list.length; r++) {
+ for (int64_t r = 0; r < (int64_t)replacement_list.length; r++) {
struct {
Text_t target, replacement;
} *entry = replacement_list.data + r * replacement_list.stride;
@@ -1194,7 +1193,7 @@ List_t Text$split(Text_t text, Text_t delimiters) {
if (delimiters.length == 0) return Text$clusters(text);
TextIter_t text_state = NEW_TEXT_ITER_STATE(text), delim_state = NEW_TEXT_ITER_STATE(delimiters);
- List_t splits = {};
+ List_t splits = EMPTY_LIST;
for (int64_t i = 0; i < text.length;) {
int64_t span_len = 0;
while (i + span_len < text.length && !_matches(&text_state, &delim_state, i + span_len)) {
@@ -1216,7 +1215,7 @@ List_t Text$split_any(Text_t text, Text_t delimiters) {
if (delimiters.length == 0) return List(text);
TextIter_t text_state = NEW_TEXT_ITER_STATE(text), delim_state = NEW_TEXT_ITER_STATE(delimiters);
- List_t splits = {};
+ List_t splits = EMPTY_LIST;
for (int64_t i = 0; i < text.length;) {
int64_t span_len = 0;
while (i + span_len < text.length
@@ -1370,8 +1369,7 @@ Text_t Text$upper(Text_t text, Text_t language) {
uint32_t buf[out_len];
ucs4_t *upper = u32_toupper(codepoints.data, (size_t)codepoints.length, uc_language, UNINORM_NFC, buf, &out_len);
OptionalText_t ret =
- Text$from_utf32((List_t){.data = upper, .length = (int64_t)out_len, .stride = sizeof(int32_t)});
- assert(ret.length >= 0);
+ Text$from_utf32((List_t){.data = upper, .length = (uint64_t)out_len, .stride = sizeof(int32_t)});
if (upper != buf) free(upper);
return ret;
}
@@ -1386,8 +1384,7 @@ Text_t Text$lower(Text_t text, Text_t language) {
uint32_t buf[out_len];
ucs4_t *lower = u32_tolower(codepoints.data, (size_t)codepoints.length, uc_language, UNINORM_NFC, buf, &out_len);
OptionalText_t ret =
- Text$from_utf32((List_t){.data = lower, .length = (int64_t)out_len, .stride = sizeof(int32_t)});
- assert(ret.length >= 0);
+ Text$from_utf32((List_t){.data = lower, .length = (uint64_t)out_len, .stride = sizeof(int32_t)});
if (lower != buf) free(lower);
return ret;
}
@@ -1402,8 +1399,7 @@ Text_t Text$title(Text_t text, Text_t language) {
uint32_t buf[out_len];
ucs4_t *title = u32_totitle(codepoints.data, (size_t)codepoints.length, uc_language, UNINORM_NFC, buf, &out_len);
OptionalText_t ret =
- Text$from_utf32((List_t){.data = title, .length = (int64_t)out_len, .stride = sizeof(int32_t)});
- assert(ret.length >= 0);
+ Text$from_utf32((List_t){.data = title, .length = (uint64_t)out_len, .stride = sizeof(int32_t)});
if (title != buf) free(title);
return ret;
}
@@ -1543,7 +1539,7 @@ Text_t Text$join(Text_t glue, List_t pieces) {
if (pieces.length == 0) return EMPTY_TEXT;
Text_t result = *(Text_t *)pieces.data;
- for (int64_t i = 1; i < pieces.length; i++) {
+ for (int64_t i = 1; i < (int64_t)pieces.length; i++) {
result = Text$concat(result, glue, *(Text_t *)(pieces.data + i * pieces.stride));
}
return result;
@@ -1551,8 +1547,8 @@ Text_t Text$join(Text_t glue, List_t pieces) {
public
List_t Text$clusters(Text_t text) {
- List_t clusters = {};
- for (int64_t i = 1; i <= text.length; i++) {
+ List_t clusters = EMPTY_LIST;
+ for (int64_t i = 1; i <= (int64_t)text.length; i++) {
Text_t cluster = Text$slice(text, I(i), I(i));
List$insert(&clusters, &cluster, I_small(0), sizeof(Text_t));
}
@@ -1561,27 +1557,27 @@ List_t Text$clusters(Text_t text) {
public
List_t Text$utf8(Text_t text) {
- if (text.length == 0) return (List_t){.atomic = 1};
- int64_t capacity = text.length;
+ if (text.length == 0) return EMPTY_ATOMIC_LIST;
+ int64_t capacity = (int64_t)text.length;
Byte_t *buf = GC_MALLOC_ATOMIC(sizeof(Byte_t[capacity]));
int64_t i = 0;
u8_buf_append(text, &buf, &capacity, &i);
return (List_t){
- .data = buf, .length = i, .stride = 1, .atomic = 1, .free = MIN(LIST_MAX_FREE_ENTRIES, capacity - i)};
+ .data = buf, .length = (uint64_t)i, .stride = 1, .atomic = 1, .free = MIN(LIST_MAX_FREE_ENTRIES, capacity - i)};
}
public
List_t Text$utf16(Text_t text) {
- if (text.length == 0) return (List_t){.atomic = 1};
+ if (text.length == 0) return EMPTY_ATOMIC_LIST;
List_t utf32 = Text$utf32(text);
List_t utf16 = {.free = MIN(LIST_MAX_FREE_ENTRIES, (uint64_t)utf32.length), .atomic = 1};
utf16.data = GC_MALLOC_ATOMIC(sizeof(int32_t[utf16.free]));
- for (int64_t i = 0; i < utf32.length; i++) {
+ for (int64_t i = 0; i < (int64_t)utf32.length; i++) {
uint16_t u16_buf[4];
size_t u16_len = sizeof(u16_buf) / sizeof(u16_buf[0]);
uint16_t *chunk_u16 = u32_to_u16(utf32.data + utf32.stride * i, 1, u16_buf, &u16_len);
if (chunk_u16 == NULL) fail("Invalid codepoints encountered!");
- List$insert_all(&utf16, (List_t){.data = chunk_u16, .stride = sizeof(uint16_t), .length = (int64_t)u16_len},
+ List$insert_all(&utf16, (List_t){.data = chunk_u16, .stride = sizeof(uint16_t), .length = (uint64_t)u16_len},
I(0), sizeof(uint16_t));
if (chunk_u16 != u16_buf) free(chunk_u16);
}
@@ -1590,10 +1586,10 @@ List_t Text$utf16(Text_t text) {
public
List_t Text$utf32(Text_t text) {
- if (text.length == 0) return (List_t){.atomic = 1};
- List_t codepoints = {.atomic = 1};
+ if (text.length == 0) return EMPTY_ATOMIC_LIST;
+ List_t codepoints = EMPTY_ATOMIC_LIST;
TextIter_t state = NEW_TEXT_ITER_STATE(text);
- for (int64_t i = 0; i < text.length; i++) {
+ for (int64_t i = 0; i < (int64_t)text.length; i++) {
int32_t grapheme = Text$get_grapheme_fast(&state, i);
if (grapheme < 0) {
for (int64_t c = 0; c < NUM_GRAPHEME_CODEPOINTS(grapheme); c++) {
@@ -1618,7 +1614,7 @@ static INLINE const char *codepoint_name(ucs4_t c) {
public
List_t Text$codepoint_names(Text_t text) {
- List_t names = {};
+ List_t names = EMPTY_LIST;
TextIter_t state = NEW_TEXT_ITER_STATE(text);
for (int64_t i = 0; i < text.length; i++) {
int32_t grapheme = Text$get_grapheme_fast(&state, i);
@@ -1653,7 +1649,7 @@ OptionalText_t Text$from_utf16(List_t units) {
uint8_t buf[length];
uint8_t *u8 = u16_to_u8(units.data, (size_t)units.length, buf, &length);
Text_t ret =
- Text$from_utf8((List_t){.data = u8, .length = (int64_t)length, .stride = sizeof(uint8_t), .atomic = 1});
+ Text$from_utf8((List_t){.data = u8, .length = (uint64_t)length, .stride = sizeof(uint8_t), .atomic = 1});
if (u8 != buf) free(u8);
return ret;
}
@@ -1663,8 +1659,8 @@ OptionalText_t Text$from_utf32(List_t codepoints) {
if (codepoints.length == 0) return EMPTY_TEXT;
if (codepoints.stride != sizeof(uint32_t)) List$compact(&codepoints, sizeof(uint32_t));
- List_t graphemes = {};
- Table_t unique_clusters = {};
+ List_t graphemes = EMPTY_ATOMIC_LIST;
+ Table_t unique_clusters = EMPTY_TABLE;
const uint32_t *pos = (const uint32_t *)codepoints.data;
const uint32_t *end = (const uint32_t *)&pos[codepoints.length];
// Iterate over grapheme clusters
@@ -1684,12 +1680,12 @@ OptionalText_t Text$from_utf32(List_t codepoints) {
if (unique_clusters.entries.length == 256) {
List_t remaining_codepoints = {
- .length = (int64_t)(end - next),
+ .length = (uint64_t)(end - next),
.data = (void *)next,
.stride = sizeof(int32_t),
};
OptionalText_t remainder = Text$from_utf32(remaining_codepoints);
- if (remainder.length < 0) return NONE_TEXT;
+ if (remainder.tag == TEXT_NONE) return NONE_TEXT;
return concat2_assuming_safe(Text$from_components(graphemes, unique_clusters), remainder);
}
}
@@ -1698,8 +1694,8 @@ OptionalText_t Text$from_utf32(List_t codepoints) {
public
OptionalText_t Text$from_codepoint_names(List_t codepoint_names) {
- List_t codepoints = {};
- for (int64_t i = 0; i < codepoint_names.length; i++) {
+ List_t codepoints = EMPTY_LIST;
+ for (int64_t i = 0; i < (int64_t)codepoint_names.length; i++) {
Text_t *name = ((Text_t *)(codepoint_names.data + i * codepoint_names.stride));
const char *name_str = Text$as_c_string(*name);
ucs4_t codepoint = unicode_name_character(name_str);
@@ -1711,9 +1707,9 @@ OptionalText_t Text$from_codepoint_names(List_t codepoint_names) {
public
List_t Text$lines(Text_t text) {
- List_t lines = {};
+ List_t lines = EMPTY_LIST;
TextIter_t state = NEW_TEXT_ITER_STATE(text);
- for (int64_t i = 0, line_start = 0; i < text.length; i++) {
+ for (int64_t i = 0, line_start = 0; i < (int64_t)text.length; i++) {
int32_t grapheme = Text$get_grapheme_fast(&state, i);
if (grapheme == '\r' && Text$get_grapheme_fast(&state, i + 1) == '\n') { // CRLF
Text_t line = Text$slice(text, I(line_start + 1), I(i));
@@ -1768,7 +1764,7 @@ Closure_t Text$by_line(Text_t text) {
PUREFUNC public bool Text$is_none(const void *t, const TypeInfo_t *info) {
(void)info;
- return ((Text_t *)t)->length < 0;
+ return ((Text_t *)t)->tag == TEXT_NONE;
}
public
diff --git a/src/stdlib/text.h b/src/stdlib/text.h
index 281c1880..821325a9 100644
--- a/src/stdlib/text.h
+++ b/src/stdlib/text.h
@@ -59,7 +59,7 @@ OptionalText_t Text$cluster(Text_t text, Int_t index_int);
const Text_t text = text_expr; \
Int_t index = index_expr; \
OptionalText_t cluster = Text$cluster(text, index); \
- if (unlikely(cluster.length < 0)) \
+ if (unlikely(cluster.tag == TEXT_NONE)) \
fail_source(__SOURCE_FILE__, start, end, "Invalid text index: ", index, " (text has length ", \
(int64_t)text.length, ")\n"); \
cluster; \
diff --git a/src/stdlib/types.h b/src/stdlib/types.h
index 2e358c6c..85567815 100644
--- a/src/stdlib/types.h
+++ b/src/stdlib/types.h
@@ -109,7 +109,7 @@ Text_t Type$as_text(const void *typeinfo, bool colorize, const TypeInfo_t *type)
t value; \
struct { \
char _padding[unpadded_size]; \
- Bool_t is_none; \
+ Bool_t has_value; \
}; \
}; \
} name
diff --git a/src/tomo.c b/src/tomo.c
index 2f1d5651..0bddb426 100644
--- a/src/tomo.c
+++ b/src/tomo.c
@@ -61,7 +61,7 @@ static struct stat compiler_stat;
static const char *paths_str(List_t paths) {
Text_t result = EMPTY_TEXT;
- for (int64_t i = 0; i < paths.length; i++) {
+ for (int64_t i = 0; i < (int64_t)paths.length; i++) {
if (i > 0) result = Texts(result, Text(" "));
result = Texts(result, Path$as_text((Path_t *)(paths.data + i * paths.stride), false, &Path$info));
}
@@ -283,14 +283,14 @@ int main(int argc, char *argv[]) {
as_owner = Texts(Text(SUDO " -u "), owner, Text(" "));
}
- for (int64_t i = 0; i < uninstall.length; i++) {
+ for (int64_t i = 0; i < (int64_t)uninstall.length; i++) {
Text_t *u = (Text_t *)(uninstall.data + i * uninstall.stride);
xsystem(as_owner, "rm -rvf '", TOMO_PATH, "'/lib/tomo_" TOMO_VERSION "/", *u);
print("Uninstalled ", *u);
}
Path_t cwd = Path$current_dir();
- for (int64_t i = 0; i < libraries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)libraries.length; i++) {
Path_t *lib = (Path_t *)(libraries.data + i * libraries.stride);
*lib = Path$resolved(*lib, cwd);
// Fork a child process to build the library to prevent cross-contamination
@@ -323,7 +323,7 @@ int main(int argc, char *argv[]) {
// Convert `foo` to `foo/foo.tm` and resolve all paths to absolute paths:
Path_t cur_dir = Path$current_dir();
- for (int64_t i = 0; i < files.length; i++) {
+ for (int64_t i = 0; i < (int64_t)files.length; i++) {
Path_t *path = (Path_t *)(files.data + i * files.stride);
if (Path$is_directory(*path, true)) *path = Path$child(*path, Texts(Path$base_name(*path), Text(".tm")));
@@ -335,7 +335,7 @@ int main(int argc, char *argv[]) {
if (!compile_exe && !stop_at_transpile && !stop_at_obj_compilation) quiet = !verbose;
- for (int64_t i = 0; i < files.length; i++) {
+ for (int64_t i = 0; i < (int64_t)files.length; i++) {
Path_t path = *(Path_t *)(files.data + i * files.stride);
if (show_parse_tree) {
ast_t *ast = parse_file(Path$as_c_string(path), NULL);
@@ -360,7 +360,7 @@ int main(int argc, char *argv[]) {
pid_t child = fork();
if (child == 0) {
env_t *env = global_env(source_mapping);
- List_t object_files = {}, extra_ldlibs = {};
+ List_t object_files = EMPTY_LIST, extra_ldlibs = EMPTY_LIST;
compile_files(env, files, &object_files, &extra_ldlibs);
compile_executable(env, path, exe_path, object_files, extra_ldlibs);
@@ -368,7 +368,7 @@ int main(int argc, char *argv[]) {
char *prog_args[1 + args.length + 1];
prog_args[0] = (char *)Path$as_c_string(exe_path);
- for (int64_t j = 0; j < args.length; j++)
+ for (int64_t j = 0; j < (int64_t)args.length; j++)
prog_args[j + 1] = Text$as_c_string(*(Text_t *)(args.data + j * args.stride));
prog_args[1 + args.length] = NULL;
execv(prog_args[0], prog_args);
@@ -379,7 +379,7 @@ int main(int argc, char *argv[]) {
}
if (compile_exe && should_install) {
- for (int64_t i = 0; i < files.length; i++) {
+ for (int64_t i = 0; i < (int64_t)files.length; i++) {
Path_t path = *(Path_t *)(files.data + i * files.stride);
Path_t exe = Path$with_extension(path, Text(""), true);
xsystem(as_owner, "cp -v '", exe, "' '", TOMO_PATH, "'/bin/");
@@ -417,7 +417,7 @@ void build_library(Path_t lib_dir) {
List_t tm_files = Path$glob(Path$child(lib_dir, Text("[!._0-9]*.tm")));
env_t *env = fresh_scope(global_env(source_mapping));
- List_t object_files = {}, extra_ldlibs = {};
+ List_t object_files = EMPTY_LIST, extra_ldlibs = EMPTY_LIST;
compile_files(env, tm_files, &object_files, &extra_ldlibs);
@@ -472,9 +472,10 @@ void install_library(Path_t lib_dir) {
}
void compile_files(env_t *env, List_t to_compile, List_t *object_files, List_t *extra_ldlibs) {
- Table_t to_link = {};
- Table_t dependency_files = {};
- for (int64_t i = 0; i < to_compile.length; i++) {
+ Table_t to_link = EMPTY_TABLE;
+ Table_t dependency_files = EMPTY_TABLE;
+ for (int64_t i = 0; i < (int64_t)to_compile.length; i++) {
+
Path_t filename = *(Path_t *)(to_compile.data + i * to_compile.stride);
Text_t extension = Path$extension(filename, true);
if (!Text$equal_values(extension, Text("tm")))
@@ -484,7 +485,7 @@ void compile_files(env_t *env, List_t to_compile, List_t *object_files, List_t *
}
// Make sure all files and dependencies have a .id file:
- for (int64_t i = 0; i < dependency_files.entries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)dependency_files.entries.length; i++) {
struct {
Path_t filename;
staleness_t staleness;
@@ -513,7 +514,7 @@ void compile_files(env_t *env, List_t to_compile, List_t *object_files, List_t *
// (Re)compile header files, eagerly for explicitly passed in files, lazily
// for downstream dependencies:
- for (int64_t i = 0; i < dependency_files.entries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)dependency_files.entries.length; i++) {
struct {
Path_t filename;
staleness_t staleness;
@@ -537,7 +538,7 @@ void compile_files(env_t *env, List_t to_compile, List_t *object_files, List_t *
// (Re)transpile and compile object files, eagerly for files explicitly
// specified and lazily for downstream dependencies:
- for (int64_t i = 0; i < dependency_files.entries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)dependency_files.entries.length; i++) {
struct {
Path_t filename;
staleness_t staleness;
@@ -564,7 +565,7 @@ void compile_files(env_t *env, List_t to_compile, List_t *object_files, List_t *
wait_for_child_success(child_processes->pid);
if (object_files) {
- for (int64_t i = 0; i < dependency_files.entries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)dependency_files.entries.length; i++) {
struct {
Path_t filename;
staleness_t staleness;
@@ -575,7 +576,7 @@ void compile_files(env_t *env, List_t to_compile, List_t *object_files, List_t *
}
}
if (extra_ldlibs) {
- for (int64_t i = 0; i < to_link.entries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)to_link.entries.length; i++) {
Text_t lib = *(Text_t *)(to_link.entries.data + i * to_link.entries.stride);
List$insert(extra_ldlibs, &lib, I(0), sizeof(Text_t));
}
@@ -584,7 +585,7 @@ void compile_files(env_t *env, List_t to_compile, List_t *object_files, List_t *
bool is_config_outdated(Path_t path) {
OptionalText_t config = Path$read(build_file(path, ".config"));
- if (config.length < 0) return true;
+ if (config.tag == TEXT_NONE) return true;
return !Text$equal_values(config, config_summary);
}
@@ -636,9 +637,9 @@ void build_file_dependency_graph(Path_t path, Table_t *to_compile, Table_t *to_l
List_t children =
Path$glob(Path$from_str(String(TOMO_PATH, "/lib/tomo_" TOMO_VERSION "/", full_name, "/[!._0-9]*.tm")));
- for (int64_t i = 0; i < children.length; i++) {
+ for (int64_t i = 0; i < (int64_t)children.length; i++) {
Path_t *child = (Path_t *)(children.data + i * children.stride);
- Table_t discarded = {.fallback = to_compile};
+ Table_t discarded = {.entries = EMPTY_LIST, .fallback = to_compile};
build_file_dependency_graph(*child, &discarded, to_link);
}
break;
@@ -676,7 +677,7 @@ void build_file_dependency_graph(Path_t path, Table_t *to_compile, Table_t *to_l
}
time_t latest_included_modification_time(Path_t path) {
- static Table_t c_modification_times = {};
+ static Table_t c_modification_times = EMPTY_TABLE;
const TypeInfo_t time_info = {.size = sizeof(time_t), .align = __alignof__(time_t), .tag = OpaqueInfo};
time_t *cached_latest = Table$get(c_modification_times, &path, Table$info(&Path$info, &time_info));
if (cached_latest) return *cached_latest;
@@ -691,7 +692,7 @@ time_t latest_included_modification_time(Path_t path) {
OptionalText_t (*next_line)(void *) = by_line.fn;
Path_t parent = Path$parent(path);
bool allow_dot_include = Path$has_extension(path, Text("s")) || Path$has_extension(path, Text("S"));
- for (Text_t line; (line = next_line(by_line.userdata)).length >= 0;) {
+ for (OptionalText_t line; (line = next_line(by_line.userdata)).tag != TEXT_NONE;) {
line = Text$trim(line, Text(" \t"), true, false);
if (!Text$starts_with(line, Text("#include"), NULL)
&& !(allow_dot_include && Text$starts_with(line, Text(".include"), NULL)))
@@ -742,7 +743,7 @@ bool is_stale(Path_t path, Path_t relative_to, bool ignore_missing) {
}
bool is_stale_for_any(Path_t path, List_t relative_to, bool ignore_missing) {
- for (int64_t i = 0; i < relative_to.length; i++) {
+ for (int64_t i = 0; i < (int64_t)relative_to.length; i++) {
Path_t r = *(Path_t *)(relative_to.data + i * relative_to.stride);
if (is_stale(path, r, ignore_missing)) return true;
}
diff --git a/src/typecheck.c b/src/typecheck.c
index eff894be..21eb7b3f 100644
--- a/src/typecheck.c
+++ b/src/typecheck.c
@@ -246,7 +246,7 @@ static env_t *load_module(env_t *env, ast_t *use_ast) {
env_t *module_file_env = fresh_scope(module_env);
module_file_env->namespace = NULL;
env_t *subenv = load_module_env(module_file_env, ast);
- for (int64_t j = 0; j < subenv->locals->entries.length; j++) {
+ for (int64_t j = 0; j < (int64_t)subenv->locals->entries.length; j++) {
struct {
const char *name;
binding_t *binding;
@@ -332,7 +332,7 @@ void prebind_statement(env_t *env, ast_t *statement) {
for (ast_list_t *stmt = extend->body ? Match(extend->body, Block)->statements : NULL; stmt; stmt = stmt->next)
prebind_statement(extended, stmt->ast);
List_t new_bindings = extended->locals->entries;
- for (int64_t i = 0; i < new_bindings.length; i++) {
+ for (int64_t i = 0; i < (int64_t)new_bindings.length; i++) {
struct {
const char *name;
binding_t *binding;
@@ -562,7 +562,7 @@ void bind_statement(env_t *env, ast_t *statement) {
for (ast_list_t *stmt = extend->body ? Match(extend->body, Block)->statements : NULL; stmt; stmt = stmt->next)
bind_statement(extended, stmt->ast);
List_t new_bindings = extended->locals->entries;
- for (int64_t i = 0; i < new_bindings.length; i++) {
+ for (int64_t i = 0; i < (int64_t)new_bindings.length; i++) {
struct {
const char *name;
binding_t *binding;
@@ -581,7 +581,7 @@ void bind_statement(env_t *env, ast_t *statement) {
if (!module_env) break;
for (Table_t *bindings = module_env->locals; bindings != module_env->globals; bindings = bindings->fallback) {
List_t entries = bindings->entries;
- for (int64_t i = 0; i < entries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)entries.length; i++) {
struct {
const char *name;
binding_t *binding;
@@ -594,7 +594,7 @@ void bind_statement(env_t *env, ast_t *statement) {
"', which would clobber another variable");
}
}
- for (int64_t i = 0; i < module_env->types->entries.length; i++) {
+ for (int64_t i = 0; i < (int64_t)module_env->types->entries.length; i++) {
struct {
const char *name;
type_t *type;
@@ -1601,7 +1601,7 @@ type_t *get_arg_type(env_t *env, arg_t *arg) {
}
bool is_valid_call(env_t *env, arg_t *spec_args, arg_ast_t *call_args, call_opts_t options) {
- Table_t used_args = {};
+ Table_t used_args = EMPTY_TABLE;
// Populate keyword args:
for (arg_ast_t *call_arg = call_args; call_arg; call_arg = call_arg->next) {