diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/environment.c | 27 | ||||
| -rw-r--r-- | src/environment.h | 1 | ||||
| -rw-r--r-- | src/stdlib/datatypes.h | 35 | ||||
| -rw-r--r-- | src/stdlib/optionals.h | 2 | ||||
| -rw-r--r-- | src/stdlib/paths.c | 111 | ||||
| -rw-r--r-- | src/stdlib/paths.h | 22 | ||||
| -rw-r--r-- | src/stdlib/result.c | 65 | ||||
| -rw-r--r-- | src/stdlib/result.h | 9 | ||||
| -rw-r--r-- | src/stdlib/tomo.h | 1 |
9 files changed, 199 insertions, 74 deletions
diff --git a/src/environment.c b/src/environment.c index bdbc8a4f..f84b6697 100644 --- a/src/environment.c +++ b/src/environment.c @@ -18,6 +18,8 @@ public type_t *PATH_TYPE = NULL; public type_t *PRESENT_TYPE = NULL; +public +type_t *RESULT_TYPE = NULL; static type_t *declare_type(env_t *env, const char *def_str) { ast_t *ast = parse_file_str(def_str); @@ -68,6 +70,7 @@ env_t *global_env(bool source_mapping) { PATH_TYPE = declare_type( env, "enum Path(AbsolutePath(components:[Text]), RelativePath(components:[Text]), HomePath(components:[Text]))"); + RESULT_TYPE = declare_type(env, "enum Result(Success, Failure(reason:Text))"); PRESENT_TYPE = declare_type(env, "struct Present()"); @@ -90,6 +93,7 @@ env_t *global_env(bool source_mapping) { MAKE_TYPE("Abort", Type(AbortType), Text("void"), Text("Abort$info")), MAKE_TYPE("Memory", Type(MemoryType), Text("void"), Text("Memory$info")), MAKE_TYPE("Present", PRESENT_TYPE, Text("Present$$type"), Text("Present$$info")), + MAKE_TYPE("Result", RESULT_TYPE, Text("Result_t"), Text("Result$$info")), MAKE_TYPE( // "Bool", Type(BoolType), Text("Bool_t"), Text("Bool$info"), {"parse", "Bool$parse", "func(text:Text, remainder:&Text?=none -> Bool?)"}), @@ -293,8 +297,9 @@ env_t *global_env(bool source_mapping) { 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))"}, // - {"append_bytes", "Path$append_bytes", "func(path:Path, bytes:[Byte], permissions=Int32(0o644))"}, // + {"append", "Path$append", "func(path:Path, text:Text, permissions=Int32(0o644) -> Result)"}, // + {"append_bytes", "Path$append_bytes", + "func(path:Path, bytes:[Byte], permissions=Int32(0o644) -> Result)"}, // {"base_name", "Path$base_name", "func(path:Path -> Text)"}, // {"by_line", "Path$by_line", "func(path:Path -> func(->Text?)?)"}, // {"can_execute", "Path$can_execute", "func(path:Path -> Bool)"}, // @@ -306,7 +311,7 @@ env_t *global_env(bool source_mapping) { {"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)"}, // + "func(path:Path, permissions=Int32(0o755), recursive=yes -> Result)"}, // {"current_dir", "Path$current_dir", "func(->Path)"}, // {"exists", "Path$exists", "func(path:Path -> Bool)"}, // {"expand_home", "Path$expand_home", "func(path:Path -> Path)"}, // @@ -324,21 +329,21 @@ env_t *global_env(bool source_mapping) { {"lines", "Path$lines", "func(path:Path -> [Text]?)"}, // {"modified", "Path$modified", "func(path:Path, follow_symlinks=yes -> Int64?)"}, // {"owner", "Path$owner", "func(path:Path, follow_symlinks=yes -> Text?)"}, // - {"parent", "Path$parent", "func(path:Path -> Path)"}, // + {"parent", "Path$parent", "func(path:Path -> Path?)"}, // {"read", "Path$read", "func(path:Path -> Text?)"}, // {"read_bytes", "Path$read_bytes", "func(path:Path, limit:Int?=none -> [Byte]?)"}, // {"relative_to", "Path$relative_to", "func(path:Path, relative_to:Path -> Path)"}, // - {"remove", "Path$remove", "func(path:Path, ignore_missing=no)"}, // + {"remove", "Path$remove", "func(path:Path, ignore_missing=no -> Result)"}, // {"resolved", "Path$resolved", "func(path:Path, relative_to=(./) -> Path)"}, // - {"set_owner", "Path$set_owner", // - "func(path:Path, owner:Text?=none, group:Text?=none, follow_symlinks=yes)"}, // + {"set_owner", "Path$set_owner", + "func(path:Path, owner:Text?=none, group:Text?=none, follow_symlinks=yes -> Result)"}, // {"sibling", "Path$sibling", "func(path:Path, name:Text -> Path)"}, // {"subdirectories", "Path$children", "func(path:Path, include_hidden=no -> [Path])"}, // {"unique_directory", "Path$unique_directory", "func(path:Path -> Path)"}, // - {"write", "Path$write", "func(path:Path, text:Text, permissions=Int32(0o644))"}, // - {"write_bytes", "Path$write_bytes", "func(path:Path, bytes:[Byte], permissions=Int32(0o644))"}, // - {"write_unique", "Path$write_unique", "func(path:Path, text:Text -> Path)"}, // - {"write_unique_bytes", "Path$write_unique_bytes", "func(path:Path, bytes:[Byte] -> Path)"}), + {"write", "Path$write", "func(path:Path, text:Text, permissions=Int32(0o644) -> Result)"}, // + {"write_bytes", "Path$write_bytes", "func(path:Path, bytes:[Byte], permissions=Int32(0o644) -> Result)"}, // + {"write_unique", "Path$write_unique", "func(path:Path, text:Text -> Path?)"}, // + {"write_unique_bytes", "Path$write_unique_bytes", "func(path:Path, bytes:[Byte] -> Path?)"}), MAKE_TYPE( // "Text", TEXT_TYPE, Text("Text_t"), Text("Text$info"), // {"as_c_string", "Text$as_c_string", "func(text:Text -> CString)"}, // diff --git a/src/environment.h b/src/environment.h index 88d36d42..ba036f2e 100644 --- a/src/environment.h +++ b/src/environment.h @@ -87,3 +87,4 @@ binding_t *get_namespace_binding(env_t *env, ast_t *self, const char *name); extern type_t *TEXT_TYPE; extern type_t *PATH_TYPE; extern type_t *PRESENT_TYPE; +extern type_t *RESULT_TYPE; diff --git a/src/stdlib/datatypes.h b/src/stdlib/datatypes.h index 49c4d835..3cd99f38 100644 --- a/src/stdlib/datatypes.h +++ b/src/stdlib/datatypes.h @@ -152,6 +152,41 @@ typedef struct { }; } Path_t; +#define $OptionalPath$$type Path_t +#define OptionalPath_t Path_t + +typedef struct Result$Success$$struct { +} Result$Success$$type; + +typedef struct { + Result$Success$$type value; + bool has_value; +} $OptionalResult$Success$$type; + +typedef struct Result$Failure$$struct { + Text_t reason; +} Result$Failure$$type; + +typedef struct { + Result$Failure$$type value; + bool has_value; +} $OptionalResult$Failure$$type; + +#define Result$Success ((Result$$type){.$tag = Result$tag$Success}) +#define SuccessResult Result$Success +#define Result$tagged$Failure(msg) ((Result$$type){.$tag = Result$tag$Failure, .Failure.reason = msg}) +#define FailureResult(...) Result$tagged$Failure(Texts(__VA_ARGS__)) + +typedef struct Result$$struct { + enum { Result$tag$none, Result$tag$Success, Result$tag$Failure } $tag; + union { + Result$Success$$type Success; + Result$Failure$$type Failure; + }; +} Result$$type; + +#define Result_t Result$$type + #define OptionalBool_t uint8_t #define OptionalList_t List_t #define OptionalTable_t Table_t diff --git a/src/stdlib/optionals.h b/src/stdlib/optionals.h index 985d6611..700a4ada 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){.$tag = Path$tag$none}) +#define NONE_PATH ((OptionalPath_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 9fb37ee3..ed8383fd 100644 --- a/src/stdlib/paths.c +++ b/src/stdlib/paths.c @@ -128,8 +128,10 @@ Path_t Path$_concat(int n, Path_t items[n]) { public Path_t Path$resolved(Path_t path, Path_t relative_to) { - if (path.$tag == Path$tag$RelativePath - && !(relative_to.$tag == Path$tag$RelativePath && relative_to.components.length == 0)) { + if (path.$tag == Path$tag$HomePath) { + return Path$expand_home(path); + } else 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, @@ -144,16 +146,18 @@ 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.$tag != relative_to.$tag) - fail("Cannot create a path relative to a different path with a mismatching type: (", path, ") relative to (", - relative_to, ")"); + if (path.$tag != relative_to.$tag) { + path = Path$resolved(path, Path$current_dir()); + relative_to = Path$resolved(relative_to, Path$current_dir()); + } 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++) { + while (shared < (int64_t)path.components.length && shared < (int64_t)relative_to.components.length) { 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; + shared += 1; } for (int64_t i = shared; i < (int64_t)relative_to.components.length; i++) @@ -163,7 +167,6 @@ Path_t Path$relative_to(Path_t path, Path_t relative_to) { Text_t *p = (Text_t *)(path.components.data + i * path.components.stride); List$insert(&result.components, p, I(0), sizeof(Text_t)); } - // clean_components(&result.components); return result; } @@ -277,7 +280,7 @@ OptionalInt64_t Path$changed(Path_t path, bool follow_symlinks) { return (OptionalInt64_t){.value = (int64_t)sb.st_ctime}; } -static void _write(Path_t path, List_t bytes, int mode, int permissions) { +static Result_t _write(Path_t path, List_t bytes, int mode, int permissions) { path = Path$expand_home(path); const char *path_str = Path$as_c_string(path); int fd = open(path_str, mode, permissions); @@ -287,36 +290,38 @@ static void _write(Path_t path, List_t bytes, int mode, int permissions) { // be closed by GC finalizers. GC_gcollect(); fd = open(path_str, mode, permissions); - if (fd == -1) fail("Could not write to file: ", path_str, "\n", strerror(errno)); } + if (fd == -1) return FailureResult("Could not write to file: ", path_str, " (", strerror(errno), ")"); } if (bytes.stride != 1) List$compact(&bytes, 1); ssize_t written = write(fd, bytes.data, (size_t)bytes.length); - if (written != (ssize_t)bytes.length) fail("Could not write to file: ", path_str, "\n", strerror(errno)); + if (written != (ssize_t)bytes.length) + return FailureResult("Could not write to file: ", path_str, " (", strerror(errno), ")"); close(fd); + return SuccessResult; } public -void Path$write(Path_t path, Text_t text, int permissions) { +Result_t Path$write(Path_t path, Text_t text, int permissions) { List_t bytes = Text$utf8(text); - _write(path, bytes, O_WRONLY | O_CREAT | O_TRUNC, permissions); + return _write(path, bytes, O_WRONLY | O_CREAT | O_TRUNC, permissions); } public -void Path$write_bytes(Path_t path, List_t bytes, int permissions) { - _write(path, bytes, O_WRONLY | O_CREAT | O_TRUNC, permissions); +Result_t Path$write_bytes(Path_t path, List_t bytes, int permissions) { + return _write(path, bytes, O_WRONLY | O_CREAT | O_TRUNC, permissions); } public -void Path$append(Path_t path, Text_t text, int permissions) { +Result_t Path$append(Path_t path, Text_t text, int permissions) { List_t bytes = Text$utf8(text); - _write(path, bytes, O_WRONLY | O_APPEND | O_CREAT, permissions); + return _write(path, bytes, O_WRONLY | O_APPEND | O_CREAT, permissions); } public -void Path$append_bytes(Path_t path, List_t bytes, int permissions) { - _write(path, bytes, O_WRONLY | O_APPEND | O_CREAT, permissions); +Result_t Path$append_bytes(Path_t path, List_t bytes, int permissions) { + return _write(path, bytes, O_WRONLY | O_APPEND | O_CREAT, permissions); } public @@ -347,8 +352,7 @@ OptionalList_t Path$read_bytes(Path_t path, OptionalInt_t count) { memcpy(content, mem, (size_t)sb.st_size); content[sb.st_size] = '\0'; close(fd); - 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, ")"); + if (count.small && (int64_t)sb.st_size < target_count) return NONE_LIST; int64_t len = count.small ? target_count : (int64_t)sb.st_size; return (List_t){.data = content, .atomic = 1, .stride = 1, .length = (uint64_t)len}; } else { @@ -376,8 +380,7 @@ OptionalList_t Path$read_bytes(Path_t path, OptionalInt_t count) { len += (size_t)just_read; } 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, ")"); + if (count.small != 0 && (int64_t)len < target_count) return NONE_LIST; return (List_t){.data = content, .atomic = 1, .stride = 1, .length = (uint64_t)len}; } } @@ -408,23 +411,24 @@ 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) { +Result_t Path$set_owner(Path_t path, OptionalText_t owner, OptionalText_t group, bool follow_symlinks) { uid_t owner_id = (uid_t)-1; if (owner.tag == TEXT_NONE) { struct passwd *pwd = getpwnam(Text$as_c_string(owner)); - if (pwd == NULL) fail("Not a valid user: ", owner); + if (pwd == NULL) return FailureResult("Not a valid user: ", owner); owner_id = pwd->pw_uid; } gid_t group_id = (gid_t)-1; if (group.tag == TEXT_NONE) { struct group *grp = getgrnam(Text$as_c_string(group)); - if (grp == NULL) fail("Not a valid group: ", group); + if (grp == NULL) return FailureResult("Not a valid group: ", group); group_id = grp->gr_gid; } const char *path_str = Path$as_c_string(path); int result = follow_symlinks ? chown(path_str, owner_id, group_id) : lchown(path_str, owner_id, group_id); - if (result < 0) fail("Could not set owner!"); + if (result < 0) return FailureResult("Could not set owner!"); + return SuccessResult; } static int _remove_files(const char *path, const struct stat *sbuf, int type, struct FTW *ftwb) { @@ -446,29 +450,30 @@ static int _remove_files(const char *path, const struct stat *sbuf, int type, st } public -void Path$remove(Path_t path, bool ignore_missing) { +Result_t Path$remove(Path_t path, bool ignore_missing) { path = Path$expand_home(path); const char *path_str = Path$as_c_string(path); struct stat sb; if (lstat(path_str, &sb) != 0) { - if (!ignore_missing) fail("Could not remove file: ", path_str, " (", strerror(errno), ")"); - return; + if (!ignore_missing) return FailureResult("Could not remove file: ", path_str, " (", strerror(errno), ")"); + return SuccessResult; } if ((sb.st_mode & S_IFMT) == S_IFREG || (sb.st_mode & S_IFMT) == S_IFLNK) { if (unlink(path_str) != 0 && !ignore_missing) - fail("Could not remove file: ", path_str, " (", strerror(errno), ")"); + return FailureResult("Could not remove file: ", path_str, " (", strerror(errno), ")"); } else if ((sb.st_mode & S_IFMT) == S_IFDIR) { const int num_open_fd = 10; if (nftw(path_str, _remove_files, num_open_fd, FTW_DEPTH | FTW_MOUNT | FTW_PHYS) < 0) - fail("Could not remove directory: %s (%s)", path_str, strerror(errno)); + return FailureResult("Could not remove directory: ", path_str, " (", strerror(errno), ")"); } else { - fail("Could not remove path: ", path_str, " (not a file or directory)"); + return FailureResult("Could not remove path: ", path_str, " (not a file or directory)"); } + return SuccessResult; } public -void Path$create_directory(Path_t path, int permissions, bool recursive) { +Result_t Path$create_directory(Path_t path, int permissions, bool recursive) { retry: path = Path$expand_home(path); const char *c_path = Path$as_c_string(path); @@ -478,19 +483,20 @@ retry: Path$create_directory(Path$parent(path), permissions, recursive); goto retry; } else if (errno != EEXIST) { - fail("Could not create directory: ", c_path, " (", strerror(errno), ")"); + return FailureResult("Could not create directory: ", c_path, " (", strerror(errno), ")"); } } + return SuccessResult; } -static List_t _filtered_children(Path_t path, bool include_hidden, mode_t filter) { +static OptionalList_t _filtered_children(Path_t path, bool include_hidden, mode_t filter) { path = Path$expand_home(path); struct dirent *dir; 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); - if (!d) fail("Could not open directory: ", path, " (", strerror(errno), ")"); + if (!d) return NONE_LIST; if (path_str[path_len - 1] == '/') --path_len; @@ -511,18 +517,22 @@ static List_t _filtered_children(Path_t path, bool include_hidden, mode_t filter } public -List_t Path$children(Path_t path, bool include_hidden) { return _filtered_children(path, include_hidden, (mode_t)-1); } +OptionalList_t Path$children(Path_t path, bool include_hidden) { + return _filtered_children(path, include_hidden, (mode_t)-1); +} public -List_t Path$files(Path_t path, bool include_hidden) { return _filtered_children(path, include_hidden, S_IFREG); } +OptionalList_t Path$files(Path_t path, bool include_hidden) { + return _filtered_children(path, include_hidden, S_IFREG); +} public -List_t Path$subdirectories(Path_t path, bool include_hidden) { +OptionalList_t Path$subdirectories(Path_t path, bool include_hidden) { return _filtered_children(path, include_hidden, S_IFDIR); } public -Path_t Path$unique_directory(Path_t path) { +OptionalPath_t Path$unique_directory(Path_t path) { path = Path$expand_home(path); const char *path_str = Path$as_c_string(path); size_t len = strlen(path_str); @@ -532,12 +542,12 @@ Path_t Path$unique_directory(Path_t path) { buf[len] = '\0'; if (buf[len - 1] == '/') buf[--len] = '\0'; char *created = mkdtemp(buf); - if (!created) fail("Failed to create temporary directory: ", path_str, " (", strerror(errno), ")"); + if (!created) return NONE_PATH; return Path$from_str(created); } public -Path_t Path$write_unique_bytes(Path_t path, List_t bytes) { +OptionalPath_t Path$write_unique_bytes(Path_t path, List_t bytes) { path = Path$expand_home(path); const char *path_str = Path$as_c_string(path); size_t len = strlen(path_str); @@ -553,23 +563,23 @@ Path_t Path$write_unique_bytes(Path_t path, List_t bytes) { ++suffixlen; int fd = mkstemps(buf, suffixlen); - if (fd == -1) fail("Could not write to unique file: ", buf, "\n", strerror(errno)); + if (fd == -1) return NONE_PATH; if (bytes.stride != 1) List$compact(&bytes, 1); ssize_t written = write(fd, bytes.data, (size_t)bytes.length); - if (written != (ssize_t)bytes.length) fail("Could not write to file: ", buf, "\n", strerror(errno)); + if (written != (ssize_t)bytes.length) fail("Could not write to file: ", buf, " (", strerror(errno), ")"); close(fd); return Path$from_str(buf); } public -Path_t Path$write_unique(Path_t path, Text_t text) { return Path$write_unique_bytes(path, Text$utf8(text)); } +OptionalPath_t Path$write_unique(Path_t path, Text_t text) { return Path$write_unique_bytes(path, Text$utf8(text)); } public -Path_t Path$parent(Path_t path) { +OptionalPath_t Path$parent(Path_t path) { if (path.$tag == Path$tag$AbsolutePath && path.components.length == 0) { - return path; + return NONE_PATH; } else if (path.components.length > 0 && !Text$equal_values( *(Text_t *)(path.components.data + path.components.stride * ((int64_t)path.components.length - 1)), @@ -631,11 +641,10 @@ public Path_t Path$sibling(Path_t path, Text_t name) { return Path$child(Path$parent(path), name); } public -Path_t Path$with_extension(Path_t path, Text_t extension, bool replace) { - if (path.components.length == 0) fail("A path with no components can't have an extension!"); +OptionalPath_t Path$with_extension(Path_t path, Text_t extension, bool replace) { + if (path.components.length == 0) return NONE_PATH; - if (Text$has(extension, Text("/")) || Text$has(extension, Text(";"))) - fail("Path extension has invalid characters: ", extension); + if (Text$has(extension, Text("/")) || Text$has(extension, Text(";"))) return NONE_PATH; Path_t result = { .$tag = path.$tag, diff --git a/src/stdlib/paths.h b/src/stdlib/paths.h index 7a175099..4e52866e 100644 --- a/src/stdlib/paths.h +++ b/src/stdlib/paths.h @@ -34,24 +34,24 @@ bool Path$can_execute(Path_t path); OptionalInt64_t Path$modified(Path_t path, bool follow_symlinks); OptionalInt64_t Path$accessed(Path_t path, bool follow_symlinks); OptionalInt64_t Path$changed(Path_t path, bool follow_symlinks); -void Path$write(Path_t path, Text_t text, int permissions); -void Path$write_bytes(Path_t path, List_t bytes, int permissions); -void Path$append(Path_t path, Text_t text, int permissions); -void Path$append_bytes(Path_t path, List_t bytes, int permissions); +Result_t Path$write(Path_t path, Text_t text, int permissions); +Result_t Path$write_bytes(Path_t path, List_t bytes, int permissions); +Result_t Path$append(Path_t path, Text_t text, int permissions); +Result_t Path$append_bytes(Path_t path, List_t bytes, int permissions); OptionalText_t Path$read(Path_t path); OptionalList_t Path$read_bytes(Path_t path, OptionalInt_t limit); -void Path$set_owner(Path_t path, OptionalText_t owner, OptionalText_t group, bool follow_symlinks); +Result_t Path$set_owner(Path_t path, OptionalText_t owner, OptionalText_t group, bool follow_symlinks); OptionalText_t Path$owner(Path_t path, bool follow_symlinks); OptionalText_t Path$group(Path_t path, bool follow_symlinks); -void Path$remove(Path_t path, bool ignore_missing); -void Path$create_directory(Path_t path, int permissions, bool recursive); +Result_t Path$remove(Path_t path, bool ignore_missing); +Result_t Path$create_directory(Path_t path, int permissions, bool recursive); List_t Path$children(Path_t path, bool include_hidden); List_t Path$files(Path_t path, bool include_hidden); List_t Path$subdirectories(Path_t path, bool include_hidden); -Path_t Path$unique_directory(Path_t path); -Path_t Path$write_unique(Path_t path, Text_t text); -Path_t Path$write_unique_bytes(Path_t path, List_t bytes); -Path_t Path$parent(Path_t path); +OptionalPath_t Path$unique_directory(Path_t path); +OptionalPath_t Path$write_unique(Path_t path, Text_t text); +OptionalPath_t Path$write_unique_bytes(Path_t path, List_t bytes); +OptionalPath_t Path$parent(Path_t path); Text_t Path$base_name(Path_t path); Text_t Path$extension(Path_t path, bool full); bool Path$has_extension(Path_t path, Text_t extension); diff --git a/src/stdlib/result.c b/src/stdlib/result.c new file mode 100644 index 00000000..8fd2ca1e --- /dev/null +++ b/src/stdlib/result.c @@ -0,0 +1,65 @@ +// Result (Success/Failure) type info +#include <err.h> +#include <gc.h> +#include <stdbool.h> +#include <stdint.h> +#include <sys/param.h> + +#include "enums.h" +#include "structs.h" +#include "text.h" +#include "util.h" + +public +const TypeInfo_t Result$Success$$info = { + .size = sizeof(Result$Success$$type), + .align = __alignof__(Result$Success$$type), + .tag = StructInfo, + .StructInfo = + { + .name = "Success", + .num_fields = 0, + }, + .metamethods = Struct$metamethods, +}; + +public +const TypeInfo_t Result$Failure$$info = { + .size = sizeof(Result$Failure$$type), + .align = __alignof__(Result$Failure$$type), + .tag = StructInfo, + .StructInfo = + { + .name = "Failure", + .num_fields = 1, + .fields = + (NamedType_t[1]){ + {.name = "reason", .type = &Text$info}, + }, + }, + .metamethods = Struct$metamethods, +}; + +public +const TypeInfo_t Result$$info = { + .size = sizeof(Result_t), + .align = __alignof__(Result_t), + .tag = EnumInfo, + .EnumInfo = + { + .name = "Result", + .num_tags = 2, + .tags = + (NamedType_t[2]){ + { + .name = "Success", + .type = &Result$Success$$info, + }, + { + .name = "Failure", + .type = &Result$Failure$$info, + }, + }, + }, + .metamethods = Enum$metamethods, +}; diff --git a/src/stdlib/result.h b/src/stdlib/result.h new file mode 100644 index 00000000..328480e7 --- /dev/null +++ b/src/stdlib/result.h @@ -0,0 +1,9 @@ +#pragma once + +// Result type for Success/Failure + +#include "types.h" + +extern const TypeInfo_t Result$Success$$info; +extern const TypeInfo_t Result$Failure$$info; +extern const TypeInfo_t Result$$info; diff --git a/src/stdlib/tomo.h b/src/stdlib/tomo.h index 1ff065b9..ff8f90a2 100644 --- a/src/stdlib/tomo.h +++ b/src/stdlib/tomo.h @@ -25,6 +25,7 @@ #include "paths.h" // IWYU pragma: export #include "pointers.h" // IWYU pragma: export #include "print.h" // IWYU pragma: export +#include "result.h" // IWYU pragma: export #include "siphash.h" // IWYU pragma: export #include "stacktrace.h" // IWYU pragma: export #include "structs.h" // IWYU pragma: export |
