Expose PathType as a proper enum
This commit is contained in:
parent
bc054ab6c6
commit
6086b2dbda
13
compile.c
13
compile.c
@ -39,7 +39,7 @@ static CORD compile_string_literal(CORD literal);
|
||||
|
||||
CORD promote_to_optional(type_t *t, CORD code)
|
||||
{
|
||||
if (t == THREAD_TYPE || t == PATH_TYPE || t->tag == MomentType) {
|
||||
if (t == THREAD_TYPE || t == PATH_TYPE || t == PATH_TYPE_TYPE || t->tag == MomentType) {
|
||||
return code;
|
||||
} else if (t->tag == IntType) {
|
||||
switch (Match(t, IntType)->bits) {
|
||||
@ -505,6 +505,7 @@ CORD compile_type(type_t *t)
|
||||
else if (t == RNG_TYPE) return "RNG_t";
|
||||
else if (t == MATCH_TYPE) return "Match_t";
|
||||
else if (t == PATH_TYPE) return "Path_t";
|
||||
else if (t == PATH_TYPE_TYPE) return "PathType_t";
|
||||
|
||||
switch (t->tag) {
|
||||
case ReturnType: errx(1, "Shouldn't be compiling ReturnType to a type");
|
||||
@ -571,6 +572,8 @@ CORD compile_type(type_t *t)
|
||||
return "OptionalMatch_t";
|
||||
if (nonnull == PATH_TYPE)
|
||||
return "OptionalPath_t";
|
||||
if (nonnull == PATH_TYPE_TYPE)
|
||||
return "OptionalPathType_t";
|
||||
auto s = Match(nonnull, StructType);
|
||||
return CORD_all(namespace_prefix(s->env, s->env->namespace->parent), "$Optional", s->name, "$$type");
|
||||
}
|
||||
@ -682,7 +685,7 @@ CORD optional_into_nonnone(type_t *t, CORD value)
|
||||
case IntType:
|
||||
return CORD_all(value, ".i");
|
||||
case StructType:
|
||||
if (t == THREAD_TYPE || t == MATCH_TYPE || t == PATH_TYPE)
|
||||
if (t == THREAD_TYPE || t == MATCH_TYPE || t == PATH_TYPE || t == PATH_TYPE_TYPE)
|
||||
return value;
|
||||
return CORD_all(value, ".value");
|
||||
default:
|
||||
@ -699,7 +702,9 @@ CORD check_none(type_t *t, CORD value)
|
||||
else if (t == MATCH_TYPE)
|
||||
return CORD_all("((", value, ").index.small == 0)");
|
||||
else if (t == PATH_TYPE)
|
||||
return CORD_all("((", value, ").type == PATH_NONE)");
|
||||
return CORD_all("((", value, ").type.$tag == PATH_NONE)");
|
||||
else if (t == PATH_TYPE_TYPE)
|
||||
return CORD_all("((", value, ").$tag == PATH_NONE)");
|
||||
else if (t->tag == BigIntType)
|
||||
return CORD_all("((", value, ").small == 0)");
|
||||
else if (t->tag == ClosureType)
|
||||
@ -2192,6 +2197,7 @@ CORD compile_none(type_t *t)
|
||||
|
||||
if (t == THREAD_TYPE) return "NULL";
|
||||
else if (t == PATH_TYPE) return "NONE_PATH";
|
||||
else if (t == PATH_TYPE_TYPE) return "((OptionalPathType_t){})";
|
||||
|
||||
switch (t->tag) {
|
||||
case BigIntType: return "NONE_INT";
|
||||
@ -3838,6 +3844,7 @@ CORD compile_type_info(type_t *t)
|
||||
else if (t == RNG_TYPE) return "&RNG$info";
|
||||
else if (t == MATCH_TYPE) return "&Match$info";
|
||||
else if (t == PATH_TYPE) return "&Path$info";
|
||||
else if (t == PATH_TYPE_TYPE) return "&PathType$info";
|
||||
|
||||
switch (t->tag) {
|
||||
case BoolType: case ByteType: case IntType: case BigIntType: case NumType: case CStringType: case MomentType:
|
||||
|
@ -17,6 +17,7 @@ type_t *MATCH_TYPE = NULL;
|
||||
type_t *RNG_TYPE = NULL;
|
||||
public type_t *PATH_TYPE = NULL;
|
||||
public type_t *THREAD_TYPE = NULL;
|
||||
public type_t *PATH_TYPE_TYPE = NULL;
|
||||
|
||||
static type_t *declare_type(env_t *env, const char *def_str)
|
||||
{
|
||||
@ -66,8 +67,9 @@ env_t *global_env(void)
|
||||
(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)");
|
||||
MATCH_TYPE = declare_type(env, "struct Match(text:Text, index:Int, captures:[Text])");
|
||||
PATH_TYPE = declare_type(env, "struct Path(type:Int32, components:[Text])");
|
||||
PATH_TYPE = declare_type(env, "struct Path(type:PathType, components:[Text])");
|
||||
THREAD_TYPE = declare_type(env, "struct Thread(; opaque)");
|
||||
RNG_TYPE = declare_type(env, "struct RNG(state:@Memory)");
|
||||
|
||||
@ -308,6 +310,11 @@ env_t *global_env(void)
|
||||
{"unix_timestamp", "Moment$unix_timestamp", "func(moment:Moment -> Int64)"},
|
||||
{"year", "Moment$year", "func(moment:Moment,timezone=none:Text -> Int)"},
|
||||
)},
|
||||
{"PathType", PATH_TYPE_TYPE, "PathType_t", "PathType$info", TypedArray(ns_entry_t,
|
||||
{"Relative", "((PathType_t){.$tag=PATH_RELATIVE})", "PathType"},
|
||||
{"Absolute", "((PathType_t){.$tag=PATH_ABSOLUTE})", "PathType"},
|
||||
{"Home", "((PathType_t){.$tag=PATH_HOME})", "PathType"},
|
||||
)},
|
||||
{"Path", PATH_TYPE, "Path_t", "Path$info", TypedArray(ns_entry_t,
|
||||
{"accessed", "Path$accessed", "func(path:Path, follow_symlinks=yes -> Moment?)"},
|
||||
{"append", "Path$append", "func(path:Path, text:Text, permissions=Int32(0o644))"},
|
||||
|
@ -75,6 +75,7 @@ extern type_t *TEXT_TYPE;
|
||||
extern type_t *MATCH_TYPE;
|
||||
extern type_t *RNG_TYPE;
|
||||
extern type_t *PATH_TYPE;
|
||||
extern type_t *PATH_TYPE_TYPE;
|
||||
extern type_t *THREAD_TYPE;
|
||||
|
||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||
|
@ -97,7 +97,12 @@ typedef struct Text_s {
|
||||
#define OptionalPattern_t Text_t
|
||||
|
||||
typedef struct {
|
||||
enum { PATH_NONE, PATH_RELATIVE, PATH_ABSOLUTE, PATH_HOME } type;
|
||||
enum { PATH_NONE, PATH_RELATIVE, PATH_ABSOLUTE, PATH_HOME } $tag;
|
||||
} PathType_t;
|
||||
#define OptionalPathType_t PathType_t
|
||||
|
||||
typedef struct {
|
||||
PathType_t type;
|
||||
Array_t components;
|
||||
} Path_t;
|
||||
#define OptionalPath_t Path_t
|
||||
|
@ -17,11 +17,13 @@
|
||||
#include <unistr.h>
|
||||
|
||||
#include "arrays.h"
|
||||
#include "enums.h"
|
||||
#include "files.h"
|
||||
#include "integers.h"
|
||||
#include "optionals.h"
|
||||
#include "paths.h"
|
||||
#include "patterns.h"
|
||||
#include "structs.h"
|
||||
#include "text.h"
|
||||
#include "types.h"
|
||||
#include "util.h"
|
||||
@ -30,7 +32,9 @@
|
||||
#include "siphash.h"
|
||||
#include "siphash-internals.h"
|
||||
|
||||
static const Path_t HOME_PATH = {.type=PATH_HOME}, ROOT_PATH = {.type=PATH_ABSOLUTE}, CURDIR_PATH = {.type=PATH_RELATIVE};
|
||||
static const Path_t HOME_PATH = {.type.$tag=PATH_HOME},
|
||||
ROOT_PATH = {.type.$tag=PATH_ABSOLUTE},
|
||||
CURDIR_PATH = {.type.$tag=PATH_RELATIVE};
|
||||
|
||||
static void clean_components(Array_t *components)
|
||||
{
|
||||
@ -60,16 +64,16 @@ public Path_t Path$from_str(const char *str)
|
||||
|
||||
Path_t result = {.components={}};
|
||||
if (str[0] == '/') {
|
||||
result.type = PATH_ABSOLUTE;
|
||||
result.type.$tag = PATH_ABSOLUTE;
|
||||
str += 1;
|
||||
} else if (str[0] == '~' && str[1] == '/') {
|
||||
result.type = PATH_HOME;
|
||||
result.type.$tag = PATH_HOME;
|
||||
str += 2;
|
||||
} else if (str[0] == '.' && str[1] == '/') {
|
||||
result.type = PATH_RELATIVE;
|
||||
result.type.$tag = PATH_RELATIVE;
|
||||
str += 2;
|
||||
} else {
|
||||
result.type = PATH_RELATIVE;
|
||||
result.type.$tag = PATH_RELATIVE;
|
||||
}
|
||||
|
||||
while (str && *str) {
|
||||
@ -100,12 +104,12 @@ public Path_t Path$from_text(Text_t text)
|
||||
|
||||
public Path_t Path$expand_home(Path_t path)
|
||||
{
|
||||
if (path.type == PATH_HOME) {
|
||||
if (path.type.$tag == PATH_HOME) {
|
||||
Path_t pwd = Path$from_str(getenv("HOME"));
|
||||
Array_t components = Array$concat(pwd.components, path.components, sizeof(Text_t));
|
||||
assert(components.length == path.components.length + pwd.components.length);
|
||||
clean_components(&components);
|
||||
path = (Path_t){.type=PATH_ABSOLUTE, .components=components};
|
||||
path = (Path_t){.type.$tag=PATH_ABSOLUTE, .components=components};
|
||||
}
|
||||
return path;
|
||||
}
|
||||
@ -116,7 +120,7 @@ public Path_t Path$_concat(int n, Path_t items[n])
|
||||
Path_t result = items[0];
|
||||
ARRAY_INCREF(result.components);
|
||||
for (int i = 1; i < n; i++) {
|
||||
if (items[i].type != PATH_RELATIVE)
|
||||
if (items[i].type.$tag != PATH_RELATIVE)
|
||||
fail("Cannot concatenate an absolute or home-based path onto another path: (%s)\n",
|
||||
Path$as_c_string(items[i]));
|
||||
Array$insert_all(&result.components, items[i].components, I(0), sizeof(Text_t));
|
||||
@ -127,8 +131,8 @@ public 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 == PATH_RELATIVE && !(relative_to.type == PATH_RELATIVE && relative_to.components.length == 0)) {
|
||||
Path_t result = {.type=relative_to.type};
|
||||
if (path.type.$tag == PATH_RELATIVE && !(relative_to.type.$tag == PATH_RELATIVE && relative_to.components.length == 0)) {
|
||||
Path_t result = {.type.$tag=relative_to.type.$tag};
|
||||
result.components = relative_to.components;
|
||||
ARRAY_INCREF(result.components);
|
||||
Array$insert_all(&result.components, path.components, I(0), sizeof(Text_t));
|
||||
@ -140,11 +144,11 @@ public 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.type.$tag != relative_to.type.$tag)
|
||||
fail("Cannot create a path relative to a different path with a mismatching type: (%k) relative to (%k)",
|
||||
(Text_t[1]){Path$as_text(&path, false, &Path$info)}, (Text_t[1]){Path$as_text(&relative_to, false, &Path$info)});
|
||||
|
||||
Path_t result = {.type=PATH_RELATIVE};
|
||||
Path_t result = {.type.$tag=PATH_RELATIVE};
|
||||
int64_t shared = 0;
|
||||
for (; shared < path.components.length && shared < relative_to.components.length; shared++) {
|
||||
Text_t *p = (Text_t*)(path.components.data + shared*path.components.stride);
|
||||
@ -532,13 +536,13 @@ public Path_t Path$write_unique(Path_t path, Text_t text)
|
||||
|
||||
public Path_t Path$parent(Path_t path)
|
||||
{
|
||||
if (path.type == PATH_ABSOLUTE && path.components.length == 0) {
|
||||
if (path.type.$tag == PATH_ABSOLUTE && path.components.length == 0) {
|
||||
return path;
|
||||
} else if (path.components.length > 0 && !Text$equal_values(*(Text_t*)(path.components.data + path.components.stride*(path.components.length-1)),
|
||||
Text(".."))) {
|
||||
return (Path_t){.type=path.type, .components=Array$slice(path.components, I(1), I(-2))};
|
||||
return (Path_t){.type.$tag=path.type.$tag, .components=Array$slice(path.components, I(1), I(-2))};
|
||||
} else {
|
||||
Path_t result = {.type=path.type, .components=path.components};
|
||||
Path_t result = {.type.$tag=path.type.$tag, .components=path.components};
|
||||
ARRAY_INCREF(result.components);
|
||||
Array$insert_value(&result.components, Text(".."), I(0), sizeof(Text_t));
|
||||
return result;
|
||||
@ -549,9 +553,9 @@ 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));
|
||||
else if (path.type == PATH_HOME)
|
||||
else if (path.type.$tag == PATH_HOME)
|
||||
return Text("~");
|
||||
else if (path.type == PATH_RELATIVE)
|
||||
else if (path.type.$tag == PATH_RELATIVE)
|
||||
return Text(".");
|
||||
else
|
||||
return EMPTY_TEXT;
|
||||
@ -573,7 +577,7 @@ public Text_t Path$extension(Path_t path, bool full)
|
||||
public Path_t Path$with_component(Path_t path, Text_t component)
|
||||
{
|
||||
Path_t result = {
|
||||
.type=path.type,
|
||||
.type.$tag=path.type.$tag,
|
||||
.components=path.components,
|
||||
};
|
||||
ARRAY_INCREF(result.components);
|
||||
@ -588,7 +592,7 @@ public Path_t Path$with_extension(Path_t path, Text_t extension, bool replace)
|
||||
fail("A path with no components can't have an extension!");
|
||||
|
||||
Path_t result = {
|
||||
.type=path.type,
|
||||
.type.$tag=path.type.$tag,
|
||||
.components=path.components,
|
||||
};
|
||||
ARRAY_INCREF(result.components);
|
||||
@ -675,7 +679,7 @@ 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);
|
||||
siphashinit(&sh, (uint64_t)path->type.$tag);
|
||||
for (int64_t i = 0; i < path->components.length; i++) {
|
||||
uint64_t item_hash = Text$hash(path->components.data + i*path->components.stride, &Text$info);
|
||||
siphashadd64bits(&sh, item_hash);
|
||||
@ -687,7 +691,7 @@ public PUREFUNC int32_t Path$compare(const void *va, const void *vb, const TypeI
|
||||
{
|
||||
(void)type;
|
||||
Path_t *a = (Path_t*)va, *b = (Path_t*)vb;
|
||||
int diff = ((int)a->type - (int)b->type);
|
||||
int diff = ((int)a->type.$tag - (int)b->type.$tag);
|
||||
if (diff != 0) return diff;
|
||||
return Array$compare(&a->components, &b->components, Array$info(&Text$info));
|
||||
}
|
||||
@ -696,32 +700,32 @@ public PUREFUNC bool Path$equal(const void *va, const void *vb, const TypeInfo_t
|
||||
{
|
||||
(void)type;
|
||||
Path_t *a = (Path_t*)va, *b = (Path_t*)vb;
|
||||
if (a->type != b->type) return false;
|
||||
if (a->type.$tag != b->type.$tag) return false;
|
||||
return Array$equal(&a->components, &b->components, Array$info(&Text$info));
|
||||
}
|
||||
|
||||
public PUREFUNC bool Path$equal_values(Path_t a, Path_t b)
|
||||
{
|
||||
if (a.type != b.type) return false;
|
||||
if (a.type.$tag != b.type.$tag) return false;
|
||||
return Array$equal(&a.components, &b.components, Array$info(&Text$info));
|
||||
}
|
||||
|
||||
public const char *Path$as_c_string(Path_t path)
|
||||
{
|
||||
if (path.components.length == 0) {
|
||||
if (path.type == PATH_ABSOLUTE) return "/";
|
||||
else if (path.type == PATH_RELATIVE) return ".";
|
||||
else if (path.type == PATH_HOME) return "~";
|
||||
if (path.type.$tag == PATH_ABSOLUTE) return "/";
|
||||
else if (path.type.$tag == PATH_RELATIVE) return ".";
|
||||
else if (path.type.$tag == PATH_HOME) return "~";
|
||||
}
|
||||
|
||||
size_t len = 0, capacity = 16;
|
||||
char *buf = GC_MALLOC_ATOMIC(capacity);
|
||||
if (path.type == PATH_ABSOLUTE) {
|
||||
if (path.type.$tag == PATH_ABSOLUTE) {
|
||||
buf[len++] = '/';
|
||||
} else if (path.type == PATH_HOME) {
|
||||
} else if (path.type.$tag == PATH_HOME) {
|
||||
buf[len++] = '~';
|
||||
buf[len++] = '/';
|
||||
} else if (path.type == PATH_RELATIVE) {
|
||||
} else if (path.type.$tag == PATH_RELATIVE) {
|
||||
if (!Text$equal_values(*(Text_t*)path.components.data, Text(".."))) {
|
||||
buf[len++] = '.';
|
||||
buf[len++] = '/';
|
||||
@ -750,11 +754,11 @@ public 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 == PATH_HOME)
|
||||
if (path->type.$tag == PATH_HOME)
|
||||
text = Text$concat(path->components.length > 0 ? Text("~/") : Text("~"), text);
|
||||
else if (path->type == PATH_ABSOLUTE)
|
||||
else if (path->type.$tag == PATH_ABSOLUTE)
|
||||
text = Text$concat(Text("/"), text);
|
||||
else if (path->type == PATH_RELATIVE && (path->components.length == 0 || !Text$equal_values(*(Text_t*)(path->components.data), Text(".."))))
|
||||
else if (path->type.$tag == PATH_RELATIVE && (path->components.length == 0 || !Text$equal_values(*(Text_t*)(path->components.data), Text(".."))))
|
||||
text = Text$concat(path->components.length > 0 ? Text("./") : Text("."), text);
|
||||
|
||||
if (color)
|
||||
@ -766,14 +770,14 @@ public 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 == PATH_NONE;
|
||||
return ((Path_t*)obj)->type.$tag == PATH_NONE;
|
||||
}
|
||||
|
||||
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);
|
||||
fputc((int)path->type.$tag, out);
|
||||
Array$serialize(&path->components, out, pointers, Array$info(&Text$info));
|
||||
}
|
||||
|
||||
@ -781,7 +785,7 @@ public void Path$deserialize(FILE *in, void *obj, Array_t *pointers, const TypeI
|
||||
{
|
||||
(void)type;
|
||||
Path_t path = {};
|
||||
path.type = fgetc(in);
|
||||
path.type.$tag = fgetc(in);
|
||||
Array$deserialize(in, &path.components, pointers, Array$info(&Text$info));
|
||||
*(Path_t*)obj = path;
|
||||
}
|
||||
@ -801,4 +805,16 @@ public const TypeInfo_t Path$info = {
|
||||
}
|
||||
};
|
||||
|
||||
public const TypeInfo_t PathType$info = {
|
||||
.size=sizeof(PathType_t),
|
||||
.align=__alignof__(PathType_t),
|
||||
.metamethods=PackedDataEnum$metamethods,
|
||||
.tag=EnumInfo,
|
||||
.EnumInfo={
|
||||
.name="PathType",
|
||||
.num_tags=3,
|
||||
.tags=((NamedType_t[3]){{.name="Relative"}, {.name="Absolute"}, {.name="Home"}}),
|
||||
},
|
||||
};
|
||||
|
||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||
|
@ -65,6 +65,7 @@ void Path$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInf
|
||||
void Path$deserialize(FILE *in, void *obj, Array_t *pointers, const TypeInfo_t *type);
|
||||
|
||||
extern const TypeInfo_t Path$info;
|
||||
extern const TypeInfo_t PathType$info;
|
||||
|
||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
|
||||
|
||||
|
2
types.c
2
types.c
@ -497,6 +497,7 @@ PUREFUNC size_t type_size(type_t *t)
|
||||
{
|
||||
if (t == THREAD_TYPE) return sizeof(pthread_t*);
|
||||
if (t == PATH_TYPE) return sizeof(Path_t);
|
||||
if (t == PATH_TYPE_TYPE) return sizeof(PathType_t);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wswitch-default"
|
||||
switch (t->tag) {
|
||||
@ -585,6 +586,7 @@ PUREFUNC size_t type_align(type_t *t)
|
||||
{
|
||||
if (t == THREAD_TYPE) return __alignof__(pthread_t*);
|
||||
if (t == PATH_TYPE) return __alignof__(Path_t);
|
||||
if (t == PATH_TYPE_TYPE) return __alignof__(PathType_t);
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wswitch-default"
|
||||
switch (t->tag) {
|
||||
|
Loading…
Reference in New Issue
Block a user