diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-12-07 21:42:45 -0500 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-12-07 21:42:45 -0500 |
| commit | 544b1fb6a70d55bf368b827136cf0f37a26e8288 (patch) | |
| tree | 52886c54934fed676263611bdb401dbeb80aac63 /src | |
| parent | efbdf7b13e4b559958ed5b1b9ca9d772ae77d702 (diff) | |
Change Paths to be an enum of their different types.
Diffstat (limited to 'src')
| -rw-r--r-- | src/compile/expressions.c | 1 | ||||
| -rw-r--r-- | src/compile/optionals.c | 11 | ||||
| -rw-r--r-- | src/compile/types.c | 3 | ||||
| -rw-r--r-- | src/environment.c | 13 | ||||
| -rw-r--r-- | src/environment.h | 1 | ||||
| -rw-r--r-- | src/stdlib/datatypes.h | 42 | ||||
| -rw-r--r-- | src/stdlib/optionals.h | 2 | ||||
| -rw-r--r-- | src/stdlib/paths.c | 226 | ||||
| -rw-r--r-- | src/stdlib/paths.h | 7 | ||||
| -rw-r--r-- | src/tomo.c | 3 | ||||
| -rw-r--r-- | src/types.c | 2 |
11 files changed, 161 insertions, 150 deletions
diff --git a/src/compile/expressions.c b/src/compile/expressions.c index 8b339352..c3918de3 100644 --- a/src/compile/expressions.c +++ b/src/compile/expressions.c @@ -57,7 +57,6 @@ Text_t compile_empty(type_t *t) { if (t->tag == OptionalType) return compile_none(t); if (t == PATH_TYPE) return Text("NONE_PATH"); - else if (t == PATH_TYPE_TYPE) return Text("PATHTYPE_ABSOLUTE"); switch (t->tag) { case BigIntType: return Text("I(0)"); diff --git a/src/compile/optionals.c b/src/compile/optionals.c index b9a3742e..83f387e2 100644 --- a/src/compile/optionals.c +++ b/src/compile/optionals.c @@ -15,18 +15,14 @@ Text_t optional_into_nonnone(type_t *t, Text_t value) { switch (t->tag) { case IntType: case ByteType: return Texts(value, ".value"); - case StructType: - if (t == PATH_TYPE || t == PATH_TYPE_TYPE) return value; - return Texts(value, ".value"); + case StructType: return Texts(value, ".value"); default: return value; } } public Text_t promote_to_optional(type_t *t, Text_t code) { - if (t == PATH_TYPE || t == PATH_TYPE_TYPE) { - return code; - } else if (t->tag == IntType) { + if (t->tag == IntType) { switch (Match(t, IntType)->bits) { case TYPE_IBITS8: return Texts("((OptionalInt8_t){.has_value=true, .value=", code, "})"); case TYPE_IBITS16: return Texts("((OptionalInt16_t){.has_value=true, .value=", code, "})"); @@ -53,7 +49,6 @@ 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("PATHTYPE_NONE"); switch (t->tag) { case BigIntType: return Text("NONE_INT"); @@ -92,8 +87,6 @@ Text_t check_none(type_t *t, Text_t value) { // NOTE: these use statement expressions ({...;}) because some compilers // complain about excessive parens around equality comparisons if (t->tag == PointerType || t->tag == FunctionType || t->tag == CStringType) return Texts("(", value, " == NULL)"); - else if (t == PATH_TYPE) return Texts("((", value, ").type == PATHTYPE_NONE)"); - else if (t == PATH_TYPE_TYPE) return Texts("((", value, ") == PATHTYPE_NONE)"); else if (t->tag == BigIntType) return Texts("((", value, ").small == 0)"); else if (t->tag == ClosureType) return Texts("((", value, ").fn == NULL)"); else if (t->tag == NumType) diff --git a/src/compile/types.c b/src/compile/types.c index 2b345b41..aac27f4c 100644 --- a/src/compile/types.c +++ b/src/compile/types.c @@ -12,7 +12,6 @@ public Text_t compile_type(type_t *t) { if (t == PATH_TYPE) return Text("Path_t"); - else if (t == PATH_TYPE_TYPE) return Text("PathType_t"); switch (t->tag) { case ReturnType: errx(1, "Shouldn't be compiling ReturnType to a type"); @@ -73,7 +72,6 @@ Text_t compile_type(type_t *t) { case TableType: return Texts("Optional", compile_type(nonnull)); case StructType: { if (nonnull == PATH_TYPE) return Text("OptionalPath_t"); - if (nonnull == PATH_TYPE_TYPE) return Text("OptionalPathType_t"); DeclareMatch(s, nonnull, StructType); return namespace_name(s->env, s->env->namespace->parent, Texts("$Optional", s->name, "$$type")); } @@ -90,7 +88,6 @@ public Text_t compile_type_info(type_t *t) { if (t == NULL) compiler_err(NULL, NULL, NULL, "Attempt to compile a NULL type"); if (t == PATH_TYPE) return Text("&Path$info"); - else if (t == PATH_TYPE_TYPE) return Text("&PathType$info"); switch (t->tag) { case BoolType: diff --git a/src/environment.c b/src/environment.c index c5932e30..bdbc8a4f 100644 --- a/src/environment.c +++ b/src/environment.c @@ -17,8 +17,6 @@ type_t *TEXT_TYPE = NULL; public type_t *PATH_TYPE = NULL; public -type_t *PATH_TYPE_TYPE = NULL; -public type_t *PRESENT_TYPE = NULL; static type_t *declare_type(env_t *env, const char *def_str) { @@ -67,8 +65,9 @@ env_t *global_env(bool source_mapping) { (void)bind_type(env, "Int", Type(BigIntType)); (void)bind_type(env, "Int32", Type(IntType, .bits = TYPE_IBITS32)); (void)bind_type(env, "Memory", Type(MemoryType)); - PATH_TYPE_TYPE = declare_type(env, "enum PathType(Relative, Absolute, Home)"); - PATH_TYPE = declare_type(env, "struct Path(type:PathType, components:[Text])"); + PATH_TYPE = declare_type( + env, + "enum Path(AbsolutePath(components:[Text]), RelativePath(components:[Text]), HomePath(components:[Text]))"); PRESENT_TYPE = declare_type(env, "struct Present()"); @@ -292,11 +291,6 @@ env_t *global_env(bool source_mapping) { #undef F #undef C MAKE_TYPE( // - "PathType", PATH_TYPE_TYPE, Text("PathType_t"), Text("PathType$info"), // - {"Relative", "PATHTYPE_RELATIVE", "PathType"}, // - {"Absolute", "PATHTYPE_ABSOLUTE", "PathType"}, // - {"Home", "PATHTYPE_HOME", "PathType"}), - MAKE_TYPE( // "Path", PATH_TYPE, Text("Path_t"), Text("Path$info"), // {"accessed", "Path$accessed", "func(path:Path, follow_symlinks=yes -> Int64?)"}, // {"append", "Path$append", "func(path:Path, text:Text, permissions=Int32(0o644))"}, // @@ -310,6 +304,7 @@ env_t *global_env(bool source_mapping) { {"child", "Path$child", "func(path:Path, child:Text -> Path)"}, // {"children", "Path$children", "func(path:Path, include_hidden=no -> [Path])"}, // {"concatenated_with", "Path$concat", "func(a,b:Path -> Path)"}, // + {"components", "Path$components", "func(path:Path -> [Text])"}, // {"create_directory", "Path$create_directory", "func(path:Path, permissions=Int32(0o755), recursive=yes)"}, // {"current_dir", "Path$current_dir", "func(->Path)"}, // diff --git a/src/environment.h b/src/environment.h index f48271b5..88d36d42 100644 --- a/src/environment.h +++ b/src/environment.h @@ -86,5 +86,4 @@ binding_t *get_namespace_binding(env_t *env, ast_t *self, const char *name); #define code_err(ast, ...) compiler_err((ast)->file, (ast)->start, (ast)->end, __VA_ARGS__) extern type_t *TEXT_TYPE; extern type_t *PATH_TYPE; -extern type_t *PATH_TYPE_TYPE; extern type_t *PRESENT_TYPE; diff --git a/src/stdlib/datatypes.h b/src/stdlib/datatypes.h index fbd2ce73..49c4d835 100644 --- a/src/stdlib/datatypes.h +++ b/src/stdlib/datatypes.h @@ -75,8 +75,8 @@ typedef struct Present$$struct { #define PRESENT_STRUCT ((Present$$type){}) typedef struct { - bool has_value; Present$$type value; + bool has_value; } $OptionalPresent$$type; #define NONE_PRESENT_STRUCT (($OptionalPresent$$type){.has_value = false}) @@ -111,14 +111,46 @@ typedef struct Text_s { }; } Text_t; -typedef enum PathEnum { PATHTYPE_NONE, PATHTYPE_RELATIVE, PATHTYPE_ABSOLUTE, PATHTYPE_HOME } PathType_t; -#define OptionalPathType_t PathType_t +typedef struct Path$AbsolutePath$$struct { + List_t components; +} Path$AbsolutePath$$type; typedef struct { - PathType_t type; + Path$AbsolutePath$$type value; + bool has_value; +} $OptionalPath$AbsolutePath$$type; + +typedef struct Path$RelativePath$$struct { + List_t components; +} Path$RelativePath$$type; + +typedef struct { + Path$RelativePath$$type value; + bool has_value; +} $OptionalPath$RelativePath$$type; + +typedef struct Path$HomePath$$struct { List_t components; +} Path$HomePath$$type; + +typedef struct { + Path$HomePath$$type value; + bool has_value; +} $OptionalPath$HomePath$$type; + +#define Path$tagged$AbsolutePath(comps) ((Path_t){.$tag = Path$tag$AbsolutePath, .AbsolutePath.components = comps}) +#define Path$tagged$RelativePath(comps) ((Path_t){.$tag = Path$tag$RelativePath, .RelativePath.components = comps}) +#define Path$tagged$HomePath(comps) ((Path_t){.$tag = Path$tag$HomePath, .HomePath.components = comps}) + +typedef struct { + enum { Path$tag$none, Path$tag$AbsolutePath, Path$tag$RelativePath, Path$tag$HomePath } $tag; + union { + Path$RelativePath$$type RelativePath; + Path$AbsolutePath$$type AbsolutePath; + Path$HomePath$$type HomePath; + List_t components; + }; } Path_t; -#define OptionalPath_t Path_t #define OptionalBool_t uint8_t #define OptionalList_t List_t diff --git a/src/stdlib/optionals.h b/src/stdlib/optionals.h index d067ec94..985d6611 100644 --- a/src/stdlib/optionals.h +++ b/src/stdlib/optionals.h @@ -15,7 +15,7 @@ #define NONE_TABLE ((OptionalTable_t){.entries.data = NULL}) #define NONE_CLOSURE ((OptionalClosure_t){.fn = NULL}) #define NONE_TEXT ((OptionalText_t){.tag = TEXT_NONE}) -#define NONE_PATH ((Path_t){.type = PATHTYPE_NONE}) +#define NONE_PATH ((Path_t){.$tag = Path$tag$none}) PUREFUNC bool is_none(const void *obj, const TypeInfo_t *non_optional_type); PUREFUNC uint64_t Optional$hash(const void *obj, const TypeInfo_t *type); diff --git a/src/stdlib/paths.c b/src/stdlib/paths.c index 6c99cf0b..9fb37ee3 100644 --- a/src/stdlib/paths.c +++ b/src/stdlib/paths.c @@ -29,11 +29,8 @@ #include "types.h" #include "util.h" -// Use inline version of the siphash code for performance: -#include "siphash-internals.h" - -static const Path_t HOME_PATH = {.type = PATHTYPE_HOME}, ROOT_PATH = {.type = PATHTYPE_ABSOLUTE}, - CURDIR_PATH = {.type = PATHTYPE_RELATIVE}; +static const Path_t HOME_PATH = Path$tagged$HomePath(EMPTY_LIST), ROOT_PATH = Path$tagged$AbsolutePath(EMPTY_LIST), + CURDIR_PATH = Path$tagged$RelativePath(EMPTY_LIST); static void clean_components(List_t *components) { for (int64_t i = 0; i < (int64_t)components->length;) { @@ -62,40 +59,41 @@ Path_t Path$from_str(const char *str) { if (strchr(str, ';') != NULL) fail("Path has illegal character (semicolon): ", str); - Path_t result = {.components = {}}; + Path_t result = {}; if (str[0] == '/') { - result.type = PATHTYPE_ABSOLUTE; + result.$tag = Path$tag$AbsolutePath; str += 1; } else if (str[0] == '~' && str[1] == '/') { - result.type = PATHTYPE_HOME; + result.$tag = Path$tag$HomePath; str += 2; } else if (str[0] == '.' && str[1] == '/') { - result.type = PATHTYPE_RELATIVE; + result.$tag = Path$tag$RelativePath; str += 2; } else { - result.type = PATHTYPE_RELATIVE; + result.$tag = Path$tag$RelativePath; } + List_t components = EMPTY_LIST; while (str && *str) { size_t component_len = strcspn(str, "/"); if (component_len > 0) { if (component_len == 1 && str[0] == '.') { // ignore /./ - } else if (component_len == 2 && strncmp(str, "..", 2) == 0 && result.components.length > 1 + } else if (component_len == 2 && strncmp(str, "..", 2) == 0 && components.length > 1 && !Text$equal_values( Text(".."), - *(Text_t *)(result.components.data - + result.components.stride * ((int64_t)result.components.length - 1)))) { + *(Text_t *)(components.data + components.stride * ((int64_t)components.length - 1)))) { // Pop off /foo/baz/.. -> /foo - List$remove_at(&result.components, I((int64_t)result.components.length), I(1), sizeof(Text_t)); + List$remove_at(&components, I((int64_t)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)); + List$insert_value(&components, component, I(0), sizeof(Text_t)); } str += component_len; } str += strspn(str, "/"); } + result.components = components; return result; } @@ -104,12 +102,12 @@ Path_t Path$from_text(Text_t text) { return Path$from_str(Text$as_c_string(text) public Path_t Path$expand_home(Path_t path) { - if (path.type == PATHTYPE_HOME) { + if (path.$tag == Path$tag$HomePath) { Path_t pwd = Path$from_str(getenv("HOME")); - List_t components = List$concat(pwd.components, path.components, sizeof(Text_t)); - assert(components.length == path.components.length + pwd.components.length); + List_t components = List$concat(pwd.AbsolutePath.components, path.HomePath.components, sizeof(Text_t)); + assert(components.length == path.HomePath.components.length + pwd.AbsolutePath.components.length); clean_components(&components); - path = (Path_t){.type = PATHTYPE_ABSOLUTE, .components = components}; + path = Path$tagged$AbsolutePath(components); } return path; } @@ -120,7 +118,7 @@ Path_t Path$_concat(int n, Path_t items[n]) { Path_t result = items[0]; LIST_INCREF(result.components); for (int i = 1; i < n; i++) { - if (items[i].type != PATHTYPE_RELATIVE) + if (items[i].$tag != Path$tag$RelativePath) fail("Cannot concatenate an absolute or home-based path onto another path: (", items[i], ")"); List$insert_all(&result.components, items[i].components, I(0), sizeof(Text_t)); } @@ -130,10 +128,12 @@ Path_t Path$_concat(int n, Path_t items[n]) { public Path_t Path$resolved(Path_t path, Path_t relative_to) { - if (path.type == PATHTYPE_RELATIVE - && !(relative_to.type == PATHTYPE_RELATIVE && relative_to.components.length == 0)) { - Path_t result = {.type = relative_to.type}; - result.components = relative_to.components; + if (path.$tag == Path$tag$RelativePath + && !(relative_to.$tag == Path$tag$RelativePath && relative_to.components.length == 0)) { + Path_t result = { + .$tag = relative_to.$tag, + .components = relative_to.components, + }; LIST_INCREF(result.components); List$insert_all(&result.components, path.components, I(0), sizeof(Text_t)); clean_components(&result.components); @@ -144,11 +144,11 @@ Path_t Path$resolved(Path_t path, Path_t relative_to) { public Path_t Path$relative_to(Path_t path, Path_t relative_to) { - if (path.type != relative_to.type) + if (path.$tag != relative_to.$tag) fail("Cannot create a path relative to a different path with a mismatching type: (", path, ") relative to (", relative_to, ")"); - Path_t result = {.type = PATHTYPE_RELATIVE}; + Path_t result = Path$tagged$RelativePath(EMPTY_LIST); int64_t shared = 0; 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); @@ -568,15 +568,15 @@ Path_t Path$write_unique(Path_t path, Text_t text) { return Path$write_unique_by public Path_t Path$parent(Path_t path) { - if (path.type == PATHTYPE_ABSOLUTE && path.components.length == 0) { + if (path.$tag == Path$tag$AbsolutePath && path.components.length == 0) { return path; } else if (path.components.length > 0 && !Text$equal_values( *(Text_t *)(path.components.data + path.components.stride * ((int64_t)path.components.length - 1)), Text(".."))) { - return (Path_t){.type = path.type, .components = List$slice(path.components, I(1), I(-2))}; + return (Path_t){.$tag = path.$tag, .components = List$slice(path.components, I(1), I(-2))}; } else { - Path_t result = {.type = path.type, .components = path.components}; + Path_t result = {.$tag = path.$tag, .components = path.components}; LIST_INCREF(result.components); List$insert_value(&result.components, Text(".."), I(0), sizeof(Text_t)); return result; @@ -587,8 +587,8 @@ public PUREFUNC Text_t Path$base_name(Path_t path) { if (path.components.length >= 1) return *(Text_t *)(path.components.data + path.components.stride * ((int64_t)path.components.length - 1)); - else if (path.type == PATHTYPE_HOME) return Text("~"); - else if (path.type == PATHTYPE_RELATIVE) return Text("."); + else if (path.$tag == Path$tag$HomePath) return Text("~"); + else if (path.$tag == Path$tag$RelativePath) return Text("."); else return EMPTY_TEXT; } @@ -618,7 +618,7 @@ public Path_t Path$child(Path_t path, Text_t name) { if (Text$has(name, Text("/")) || Text$has(name, Text(";"))) fail("Path name has invalid characters: ", name); Path_t result = { - .type = path.type, + .$tag = path.$tag, .components = path.components, }; LIST_INCREF(result.components); @@ -638,7 +638,7 @@ Path_t Path$with_extension(Path_t path, Text_t extension, bool replace) { fail("Path extension has invalid characters: ", extension); Path_t result = { - .type = path.type, + .$tag = path.$tag, .components = path.components, }; LIST_INCREF(result.components); @@ -760,55 +760,19 @@ Path_t Path$current_dir(void) { } public -PUREFUNC uint64_t Path$hash(const void *obj, const TypeInfo_t *type) { - (void)type; - Path_t *path = (Path_t *)obj; - siphash sh; - siphashinit(&sh, (uint64_t)path->type); - 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); - } - return siphashfinish_last_part(&sh, (uint64_t)path->components.length); -} - -public -PUREFUNC int32_t Path$compare(const void *va, const void *vb, const TypeInfo_t *type) { - (void)type; - Path_t *a = (Path_t *)va, *b = (Path_t *)vb; - int diff = ((int)a->type - (int)b->type); - if (diff != 0) return diff; - return List$compare(&a->components, &b->components, List$info(&Text$info)); -} - -public -PUREFUNC bool Path$equal(const void *va, const void *vb, const TypeInfo_t *type) { - (void)type; - Path_t *a = (Path_t *)va, *b = (Path_t *)vb; - if (a->type != b->type) return false; - return List$equal(&a->components, &b->components, List$info(&Text$info)); -} - -public -PUREFUNC bool Path$equal_values(Path_t a, Path_t b) { - if (a.type != b.type) return false; - return List$equal(&a.components, &b.components, List$info(&Text$info)); -} - -public int Path$print(FILE *f, Path_t path) { if (path.components.length == 0) { - if (path.type == PATHTYPE_ABSOLUTE) return fputs("/", f); - else if (path.type == PATHTYPE_RELATIVE) return fputs(".", f); - else if (path.type == PATHTYPE_HOME) return fputs("~", f); + if (path.$tag == Path$tag$AbsolutePath) return fputs("/", f); + else if (path.$tag == Path$tag$RelativePath) return fputs(".", f); + else if (path.$tag == Path$tag$HomePath) return fputs("~", f); } int n = 0; - if (path.type == PATHTYPE_ABSOLUTE) { + if (path.$tag == Path$tag$AbsolutePath) { n += fputc('/', f); - } else if (path.type == PATHTYPE_HOME) { + } else if (path.$tag == Path$tag$HomePath) { n += fputs("~/", f); - } else if (path.type == PATHTYPE_RELATIVE) { + } else if (path.$tag == Path$tag$RelativePath) { if (!Text$equal_values(*(Text_t *)path.components.data, Text(".."))) n += fputs("./", f); } @@ -829,9 +793,9 @@ Text_t Path$as_text(const void *obj, bool color, const TypeInfo_t *type) { if (!obj) return Text("Path"); Path_t *path = (Path_t *)obj; Text_t text = Text$join(Text("/"), path->components); - if (path->type == PATHTYPE_HOME) text = Text$concat(path->components.length > 0 ? Text("~/") : Text("~"), text); - else if (path->type == PATHTYPE_ABSOLUTE) text = Text$concat(Text("/"), text); - else if (path->type == PATHTYPE_RELATIVE + if (path->$tag == Path$tag$HomePath) text = Text$concat(path->components.length > 0 ? Text("~/") : Text("~"), text); + else if (path->$tag == Path$tag$AbsolutePath) text = Text$concat(Text("/"), text); + else if (path->$tag == Path$tag$RelativePath && (path->components.length == 0 || !Text$equal_values(*(Text_t *)(path->components.data), Text("..")))) text = Text$concat(path->components.length > 0 ? Text("./") : Text("."), text); @@ -841,52 +805,80 @@ Text_t Path$as_text(const void *obj, bool color, const TypeInfo_t *type) { } public -CONSTFUNC bool Path$is_none(const void *obj, const TypeInfo_t *type) { - (void)type; - return ((Path_t *)obj)->type == PATHTYPE_NONE; -} +const TypeInfo_t Path$AbsolutePath$$info = { + .size = sizeof(Path$AbsolutePath$$type), + .align = __alignof__(Path$AbsolutePath$$type), + .metamethods = Struct$metamethods, + .tag = StructInfo, + .StructInfo = + { + .name = "AbsolutePath", + .num_fields = 1, + .fields = (NamedType_t[1]){{ + .name = "components", + .type = List$info(&Text$info), + }}, + }, +}; public -void Path$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) { - (void)type; - Path_t *path = (Path_t *)obj; - fputc((int)path->type, out); - List$serialize(&path->components, out, pointers, List$info(&Text$info)); -} +const TypeInfo_t Path$RelativePath$$info = { + .size = sizeof(Path$RelativePath$$type), + .align = __alignof__(Path$RelativePath$$type), + .metamethods = Struct$metamethods, + .tag = StructInfo, + .StructInfo = + { + .name = "RelativePath", + .num_fields = 1, + .fields = (NamedType_t[1]){{ + .name = "components", + .type = List$info(&Text$info), + }}, + }, +}; public -void Path$deserialize(FILE *in, void *obj, List_t *pointers, const TypeInfo_t *type) { - (void)type; - Path_t path = {}; - path.type = fgetc(in); - List$deserialize(in, &path.components, pointers, List$info(&Text$info)); - *(Path_t *)obj = path; -} - -public -const TypeInfo_t Path$info = {.size = sizeof(Path_t), - .align = __alignof__(Path_t), - .tag = OpaqueInfo, - .metamethods = { - .as_text = Path$as_text, - .hash = Path$hash, - .compare = Path$compare, - .equal = Path$equal, - .is_none = Path$is_none, - .serialize = Path$serialize, - .deserialize = Path$deserialize, - }}; - -public -const TypeInfo_t PathType$info = { - .size = sizeof(PathType_t), - .align = __alignof__(PathType_t), - .metamethods = PackedDataEnum$metamethods, +const TypeInfo_t Path$HomePath$$info = { + .size = sizeof(Path$HomePath$$type), + .align = __alignof__(Path$HomePath$$type), + .metamethods = Struct$metamethods, + .tag = StructInfo, + .StructInfo = + { + .name = "HomePath", + .num_fields = 1, + .fields = (NamedType_t[1]){{ + .name = "components", + .type = List$info(&Text$info), + }}, + }, +}; + +public +const TypeInfo_t Path$info = { + .size = sizeof(Path_t), + .align = __alignof__(Path_t), .tag = EnumInfo, .EnumInfo = { - .name = "PathType", + .name = "Path", .num_tags = 3, - .tags = ((NamedType_t[3]){{.name = "Relative"}, {.name = "Absolute"}, {.name = "Home"}}), + .tags = + (NamedType_t[3]){ + {.name = "AbsolutePath", &Path$AbsolutePath$$info}, + {.name = "RelativePath", &Path$RelativePath$$info}, + {.name = "HomePath", &Path$HomePath$$info}, + }, + }, + .metamethods = + { + .as_text = Path$as_text, + .compare = Enum$compare, + .equal = Enum$equal, + .hash = Enum$hash, + .is_none = Enum$is_none, + .serialize = Enum$serialize, + .deserialize = Enum$deserialize, }, }; diff --git a/src/stdlib/paths.h b/src/stdlib/paths.h index 677631b2..7a175099 100644 --- a/src/stdlib/paths.h +++ b/src/stdlib/paths.h @@ -12,6 +12,9 @@ Path_t Path$from_str(const char *str); Path_t Path$from_text(Text_t text); // int Path$print(FILE *f, Path_t path); +// UNSAFE: this works because each type of path has a .components in the same place +#define Path$components(path) ((path).components) +// END UNSAFE const char *Path$as_c_string(Path_t path); #define Path(str) Path$from_str(str) Path_t Path$_concat(int n, Path_t items[n]); @@ -69,5 +72,7 @@ bool Path$is_none(const void *obj, const TypeInfo_t *type); void Path$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type); void Path$deserialize(FILE *in, void *obj, List_t *pointers, const TypeInfo_t *type); +extern const TypeInfo_t Path$AbsolutePath$$info; +extern const TypeInfo_t Path$RelativePath$$info; +extern const TypeInfo_t Path$HomePath$$info; extern const TypeInfo_t Path$info; -extern const TypeInfo_t PathType$info; @@ -28,6 +28,7 @@ #include "stdlib/c_strings.h" #include "stdlib/cli.h" #include "stdlib/datatypes.h" +#include "stdlib/enums.h" #include "stdlib/lists.h" #include "stdlib/optionals.h" #include "stdlib/paths.h" @@ -511,7 +512,7 @@ void install_library(Path_t lib_dir) { Text_t lib_name = get_library_name(lib_dir); Path_t dest = Path$child(Path$from_str(String(TOMO_PATH, "/lib/tomo@" TOMO_VERSION)), lib_name); print("Installing ", lib_dir, " into ", dest); - if (!Path$equal_values(lib_dir, dest)) { + if (!Enum$equal(&lib_dir, &dest, &Path$info)) { if (verbose) whisper("Clearing out any pre-existing version of ", lib_name); xsystem(as_owner, "rm -rf '", dest, "'"); if (verbose) whisper("Moving files to ", dest); diff --git a/src/types.c b/src/types.c index 5c52992b..46df5c64 100644 --- a/src/types.c +++ b/src/types.c @@ -516,7 +516,6 @@ PUREFUNC size_t unpadded_struct_size(type_t *t) { PUREFUNC size_t type_size(type_t *t) { if (t == PATH_TYPE) return sizeof(Path_t); - if (t == PATH_TYPE_TYPE) return sizeof(PathType_t); #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wswitch-default" @@ -605,7 +604,6 @@ PUREFUNC size_t type_size(type_t *t) { PUREFUNC size_t type_align(type_t *t) { if (t == PATH_TYPE) return __alignof__(Path_t); - if (t == PATH_TYPE_TYPE) return __alignof__(PathType_t); #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wswitch-default" |
