1
0
mirror of https://github.com/janet-lang/janet synced 2025-01-24 22:26:52 +00:00

Retab value.c

This commit is contained in:
Calvin Rose 2017-03-10 00:26:28 -05:00
parent ce759d901e
commit 9c94bfab4d

276
value.c
View File

@ -87,57 +87,57 @@ uint8_t *gst_to_string(Gst *vm, GstValue x) {
case GST_ARRAY: case GST_ARRAY:
{ {
uint32_t i; uint32_t i;
GstBuffer *b = gst_buffer(vm, 40); GstBuffer *b = gst_buffer(vm, 40);
gst_buffer_push(vm, b, '['); gst_buffer_push(vm, b, '[');
for (i = 0; i < x.data.array->count; ++i) { for (i = 0; i < x.data.array->count; ++i) {
uint8_t *substr = gst_to_string(vm, x.data.array->data[i]); uint8_t *substr = gst_to_string(vm, x.data.array->data[i]);
gst_buffer_append(vm, b, substr, gst_string_length(substr)); gst_buffer_append(vm, b, substr, gst_string_length(substr));
if (i < x.data.array->count - 1) if (i < x.data.array->count - 1)
gst_buffer_push(vm, b, ' '); gst_buffer_push(vm, b, ' ');
} }
gst_buffer_push(vm, b, ']'); gst_buffer_push(vm, b, ']');
return gst_buffer_to_string(vm, b); return gst_buffer_to_string(vm, b);
} }
case GST_TUPLE: case GST_TUPLE:
{ {
uint32_t i, count; uint32_t i, count;
GstBuffer *b = gst_buffer(vm, 40); GstBuffer *b = gst_buffer(vm, 40);
GstValue *tuple = x.data.tuple; GstValue *tuple = x.data.tuple;
gst_buffer_push(vm, b, '('); gst_buffer_push(vm, b, '(');
count = gst_tuple_length(tuple); count = gst_tuple_length(tuple);
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
uint8_t *substr = gst_to_string(vm, tuple[i]); uint8_t *substr = gst_to_string(vm, tuple[i]);
gst_buffer_append(vm, b, substr, gst_string_length(substr)); gst_buffer_append(vm, b, substr, gst_string_length(substr));
if (i < count - 1) if (i < count - 1)
gst_buffer_push(vm, b, ' '); gst_buffer_push(vm, b, ' ');
} }
gst_buffer_push(vm, b, ')'); gst_buffer_push(vm, b, ')');
return gst_buffer_to_string(vm, b); return gst_buffer_to_string(vm, b);
} }
case GST_OBJECT: case GST_OBJECT:
{ {
uint32_t i, count; uint32_t i, count;
GstBucket *bucket; GstBucket *bucket;
GstBuffer *b = gst_buffer(vm, 40); GstBuffer *b = gst_buffer(vm, 40);
GstObject *object = x.data.object; GstObject *object = x.data.object;
gst_buffer_push(vm, b, '{'); gst_buffer_push(vm, b, '{');
count = 0; count = 0;
for (i = 0; i < object->capacity; ++i) { for (i = 0; i < object->capacity; ++i) {
bucket = object->buckets[i]; bucket = object->buckets[i];
while (bucket != NULL) { while (bucket != NULL) {
uint8_t *substr = gst_to_string(vm, bucket->key); uint8_t *substr = gst_to_string(vm, bucket->key);
gst_buffer_append(vm, b, substr, gst_string_length(substr)); gst_buffer_append(vm, b, substr, gst_string_length(substr));
gst_buffer_push(vm, b, ' '); gst_buffer_push(vm, b, ' ');
substr = gst_to_string(vm, bucket->value); substr = gst_to_string(vm, bucket->value);
gst_buffer_append(vm, b, substr, gst_string_length(substr)); gst_buffer_append(vm, b, substr, gst_string_length(substr));
count++; count++;
if (count < object->count) if (count < object->count)
gst_buffer_push(vm, b, ' '); gst_buffer_push(vm, b, ' ');
bucket = bucket->next; bucket = bucket->next;
} }
} }
gst_buffer_push(vm, b, '}'); gst_buffer_push(vm, b, '}');
return gst_buffer_to_string(vm, b); return gst_buffer_to_string(vm, b);
} }
case GST_STRING: case GST_STRING:
return x.data.string; return x.data.string;
@ -157,7 +157,7 @@ uint8_t *gst_to_string(Gst *vm, GstValue x) {
/* GST string version */ /* GST string version */
uint32_t gst_string_calchash(const uint8_t *str) { uint32_t gst_string_calchash(const uint8_t *str) {
return gst_cstring_calchash(str, gst_string_length(str)); return gst_cstring_calchash(str, gst_string_length(str));
} }
/* Simple hash function (djb2) */ /* Simple hash function (djb2) */
@ -225,13 +225,13 @@ int gst_equals(GstValue x, GstValue y) {
} }
result = 1; result = 1;
{ {
uint32_t i; uint32_t i;
for (i = 0; i < gst_tuple_length(x.data.tuple); ++i) { for (i = 0; i < gst_tuple_length(x.data.tuple); ++i) {
if (!gst_equals(x.data.tuple[i], y.data.tuple[i])) { if (!gst_equals(x.data.tuple[i], y.data.tuple[i])) {
result = 0; result = 0;
break; break;
} }
} }
} }
break; break;
default: default:
@ -338,21 +338,21 @@ int gst_compare(GstValue x, GstValue y) {
} }
/* Lower indices are most significant */ /* Lower indices are most significant */
case GST_TUPLE: case GST_TUPLE:
{ {
uint32_t i; uint32_t i;
uint32_t xlen = gst_tuple_length(x.data.tuple); uint32_t xlen = gst_tuple_length(x.data.tuple);
uint32_t ylen = gst_tuple_length(y.data.tuple); uint32_t ylen = gst_tuple_length(y.data.tuple);
uint32_t count = xlen < ylen ? xlen : ylen; uint32_t count = xlen < ylen ? xlen : ylen;
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
int comp = gst_compare(x.data.tuple[i], y.data.tuple[i]); int comp = gst_compare(x.data.tuple[i], y.data.tuple[i]);
if (comp != 0) return comp; if (comp != 0) return comp;
} }
if (xlen < ylen) if (xlen < ylen)
return -1; return -1;
else if (xlen > ylen) else if (xlen > ylen)
return 1; return 1;
return 0; return 0;
} }
break; break;
default: default:
if (x.data.string == y.data.string) { if (x.data.string == y.data.string) {
@ -371,28 +371,28 @@ int gst_compare(GstValue x, GstValue y) {
/* This probably isn't very fast - look at Lua conversion function. /* This probably isn't very fast - look at Lua conversion function.
* I would like to keep this standard C for as long as possible, though. */ * I would like to keep this standard C for as long as possible, though. */
static int32_t to_index(GstNumber raw, int64_t len) { static int32_t to_index(GstNumber raw, int64_t len) {
int32_t toInt = raw; int32_t toInt = raw;
if ((GstNumber) toInt == raw) { if ((GstNumber) toInt == raw) {
/* We were able to convert */ /* We were able to convert */
if (toInt < 0 && len > 0) { if (toInt < 0 && len > 0) {
/* Index from end */ /* Index from end */
if (toInt < -len) return -1; if (toInt < -len) return -1;
return len + toInt; return len + toInt;
} else { } else {
/* Normal indexing */ /* Normal indexing */
if (toInt >= len) return -1; if (toInt >= len) return -1;
return toInt; return toInt;
} }
} else { } else {
return -1; return -1;
} }
} }
/* Convert a number into a byte. */ /* Convert a number into a byte. */
static uint8_t to_byte(GstNumber raw) { static uint8_t to_byte(GstNumber raw) {
if (raw > 255) return 255; if (raw > 255) return 255;
if (raw < 0) return 0; if (raw < 0) return 0;
return (uint8_t) raw; return (uint8_t) raw;
} }
/* Get a value out af an associated data structure. /* Get a value out af an associated data structure.
@ -401,74 +401,74 @@ static uint8_t to_byte(GstNumber raw) {
const char *gst_get(GstValue ds, GstValue key, GstValue *out) { const char *gst_get(GstValue ds, GstValue key, GstValue *out) {
int32_t index; int32_t index;
GstValue ret; GstValue ret;
switch (ds.type) { switch (ds.type) {
case GST_ARRAY: case GST_ARRAY:
if (key.type != GST_NUMBER) return "expected numeric key"; if (key.type != GST_NUMBER) return "expected numeric key";
index = to_index(key.data.number, ds.data.array->count); index = to_index(key.data.number, ds.data.array->count);
if (index == -1) return "invalid array access"; if (index == -1) return "invalid array access";
ret = ds.data.array->data[index]; ret = ds.data.array->data[index];
break; break;
case GST_TUPLE: case GST_TUPLE:
if (key.type != GST_NUMBER) return "expected numeric key"; if (key.type != GST_NUMBER) return "expected numeric key";
index = to_index(key.data.number, gst_tuple_length(ds.data.tuple)); index = to_index(key.data.number, gst_tuple_length(ds.data.tuple));
if (index < 0) return "invalid tuple access"; if (index < 0) return "invalid tuple access";
ret = ds.data.tuple[index]; ret = ds.data.tuple[index];
break; break;
case GST_BYTEBUFFER: case GST_BYTEBUFFER:
if (key.type != GST_NUMBER) return "expected numeric key"; if (key.type != GST_NUMBER) return "expected numeric key";
index = to_index(key.data.number, ds.data.buffer->count); index = to_index(key.data.number, ds.data.buffer->count);
if (index == -1) return "invalid buffer access"; if (index == -1) return "invalid buffer access";
ret.type = GST_NUMBER; ret.type = GST_NUMBER;
ret.data.number = ds.data.buffer->data[index]; ret.data.number = ds.data.buffer->data[index];
break; break;
case GST_STRING: case GST_STRING:
if (key.type != GST_NUMBER) return "expected numeric key"; if (key.type != GST_NUMBER) return "expected numeric key";
index = to_index(key.data.number, gst_string_length(ds.data.string)); index = to_index(key.data.number, gst_string_length(ds.data.string));
if (index == -1) return "invalid string access"; if (index == -1) return "invalid string access";
ret.type = GST_NUMBER; ret.type = GST_NUMBER;
ret.data.number = ds.data.string[index]; ret.data.number = ds.data.string[index];
break; break;
case GST_OBJECT: case GST_OBJECT:
ret = gst_object_get(ds.data.object, key); ret = gst_object_get(ds.data.object, key);
break; break;
default: default:
return "cannot get"; return "cannot get";
} }
*out = ret; *out = ret;
return NULL; return NULL;
} }
/* Set a value in an associative data structure. Returns possible /* Set a value in an associative data structure. Returns possible
* error message, and NULL if no error. */ * error message, and NULL if no error. */
const char *gst_set(Gst *vm, GstValue ds, GstValue key, GstValue value) { const char *gst_set(Gst *vm, GstValue ds, GstValue key, GstValue value) {
int32_t index; int32_t index;
switch (ds.type) { switch (ds.type) {
case GST_ARRAY: case GST_ARRAY:
if (ds.data.array->flags & GST_IMMUTABLE) if (ds.data.array->flags & GST_IMMUTABLE)
return "cannot set immutable value"; return "cannot set immutable value";
if (key.type != GST_NUMBER) return "expected numeric key"; if (key.type != GST_NUMBER) return "expected numeric key";
index = to_index(key.data.number, ds.data.array->count); index = to_index(key.data.number, ds.data.array->count);
if (index == -1) return "invalid array access"; if (index == -1) return "invalid array access";
ds.data.array->data[index] = value; ds.data.array->data[index] = value;
break; break;
case GST_BYTEBUFFER: case GST_BYTEBUFFER:
if (ds.data.buffer->flags & GST_IMMUTABLE) if (ds.data.buffer->flags & GST_IMMUTABLE)
return "cannot set immutable value"; return "cannot set immutable value";
if (key.type != GST_NUMBER) return "expected numeric key"; if (key.type != GST_NUMBER) return "expected numeric key";
if (value.type != GST_NUMBER) return "expected numeric value"; if (value.type != GST_NUMBER) return "expected numeric value";
index = to_index(key.data.number, ds.data.buffer->count); index = to_index(key.data.number, ds.data.buffer->count);
if (index == -1) return "invalid buffer access"; if (index == -1) return "invalid buffer access";
ds.data.buffer->data[index] = to_byte(value.data.number); ds.data.buffer->data[index] = to_byte(value.data.number);
break; break;
case GST_OBJECT: case GST_OBJECT:
if (ds.data.object->flags & GST_IMMUTABLE) if (ds.data.object->flags & GST_IMMUTABLE)
return "cannot set immutable value"; return "cannot set immutable value";
gst_object_put(vm, ds.data.object, key, value); gst_object_put(vm, ds.data.object, key, value);
break; break;
default: default:
return "cannot set"; return "cannot set";
} }
return NULL; return NULL;
} }
/* Get the class object of a value */ /* Get the class object of a value */
@ -476,21 +476,21 @@ GstValue gst_get_class(GstValue x) {
GstValue ret; GstValue ret;
ret.type = GST_NIL; ret.type = GST_NIL;
switch (x.type) { switch (x.type) {
case GST_OBJECT: case GST_OBJECT:
if (x.data.object->meta != NULL) { if (x.data.object->meta != NULL) {
ret.type = GST_OBJECT; ret.type = GST_OBJECT;
ret.data.object = x.data.object->meta; ret.data.object = x.data.object->meta;
} }
break; break;
case GST_USERDATA: case GST_USERDATA:
{ {
GstUserdataHeader *header = (GstUserdataHeader *)x.data.pointer - 1; GstUserdataHeader *header = (GstUserdataHeader *)x.data.pointer - 1;
if (header->meta != NULL) { if (header->meta != NULL) {
ret.type = GST_OBJECT; ret.type = GST_OBJECT;
ret.data.object = header->meta; ret.data.object = header->meta;
} }
} }
break; break;
default: default:
break; break;
} }
@ -500,11 +500,11 @@ GstValue gst_get_class(GstValue x) {
/* Set the class object of a value. Returns possible c error string */ /* Set the class object of a value. Returns possible c error string */
const char *gst_set_class(GstValue x, GstValue class) { const char *gst_set_class(GstValue x, GstValue class) {
switch (x.type) { switch (x.type) {
case GST_OBJECT: case GST_OBJECT:
if (class.type != GST_OBJECT) return "class must be of type object"; if (class.type != GST_OBJECT) return "class must be of type object";
/* TODO - check for class immutability */ /* TODO - check for class immutability */
x.data.object->meta = class.data.object; x.data.object->meta = class.data.object;
break; break;
default: default:
return "cannot set class object"; return "cannot set class object";
} }