1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-29 03:19:54 +00:00

Merge branch 'master' of github.com:janet-lang/janet into threads-3

This commit is contained in:
Calvin Rose 2019-12-01 21:26:22 -06:00
commit 5b1e59b535
6 changed files with 72 additions and 63 deletions

View File

@ -262,59 +262,15 @@ static Janet janet_core_setdyn(int32_t argc, Janet *argv) {
return argv[1]; return argv[1];
} }
// XXX inline asm function with a new op - OP_GET_PERMISSIVE?
// This would match up with OP_GET which is used for 'in'.
static Janet janet_core_get(int32_t argc, Janet *argv) { static Janet janet_core_get(int32_t argc, Janet *argv) {
janet_arity(argc, 2, 3); janet_arity(argc, 2, 3);
Janet ds = argv[0]; Janet result = janet_get_permissive(argv[0], argv[1]);
Janet key = argv[1]; if (argc == 3 && janet_checktype(result, JANET_NIL)) {
Janet dflt = argc == 3 ? argv[2] : janet_wrap_nil(); return argv[2];
JanetType t = janet_type(argv[0]);
switch (t) {
default:
return dflt;
case JANET_STRING:
case JANET_SYMBOL:
case JANET_KEYWORD: {
if (!janet_checkint(key)) return dflt;
int32_t index = janet_unwrap_integer(key);
if (index < 0) return dflt;
const uint8_t *str = janet_unwrap_string(ds);
if (index >= janet_string_length(str)) return dflt;
return janet_wrap_integer(str[index]);
}
case JANET_ABSTRACT: {
void *abst = janet_unwrap_abstract(ds);
JanetAbstractType *type = (JanetAbstractType *)janet_abstract_type(abst);
if (!type->get) return dflt;
return (type->get)(abst, key);
}
case JANET_ARRAY:
case JANET_TUPLE: {
if (!janet_checkint(key)) return dflt;
int32_t index = janet_unwrap_integer(key);
if (index < 0) return dflt;
if (t == JANET_ARRAY) {
JanetArray *a = janet_unwrap_array(ds);
if (index >= a->count) return dflt;
return a->data[index];
} else {
const Janet *t = janet_unwrap_tuple(ds);
if (index >= janet_tuple_length(t)) return dflt;
return t[index];
}
}
case JANET_TABLE: {
JanetTable *flag = NULL;
Janet ret = janet_table_get_ex(janet_unwrap_table(ds), key, &flag);
if (flag == NULL) return dflt;
return ret;
}
case JANET_STRUCT: {
const JanetKV *st = janet_unwrap_struct(ds);
Janet ret = janet_struct_get(st, key);
if (janet_checktype(ret, JANET_NIL)) return dflt;
return ret;
}
} }
return result;
} }
static Janet janet_core_native(int32_t argc, Janet *argv) { static Janet janet_core_native(int32_t argc, Janet *argv) {
@ -744,7 +700,7 @@ static const JanetReg corelib_cfuns[] = {
"get", janet_core_get, "get", janet_core_get,
JDOC("(get ds key &opt dflt)\n\n" JDOC("(get ds key &opt dflt)\n\n"
"Get the value mapped to key in data structure ds, and return dflt or nil if not found. " "Get the value mapped to key in data structure ds, and return dflt or nil if not found. "
"Similar to get, but will not throw an error if the key is invalid for the data structure " "Similar to in, but will not throw an error if the key is invalid for the data structure "
"unless the data structure is an abstract type. In that case, the abstract type getter may throw " "unless the data structure is an abstract type. In that case, the abstract type getter may throw "
"an error.") "an error.")
}, },
@ -963,7 +919,7 @@ static const uint32_t resume_asm[] = {
JOP_RESUME | (1 << 24), JOP_RESUME | (1 << 24),
JOP_RETURN JOP_RETURN
}; };
static const uint32_t get_asm[] = { static const uint32_t in_asm[] = {
JOP_GET | (1 << 24), JOP_GET | (1 << 24),
JOP_LOAD_NIL | (3 << 8), JOP_LOAD_NIL | (3 << 8),
JOP_EQUALS | (3 << 8) | (3 << 24), JOP_EQUALS | (3 << 8) | (3 << 24),
@ -1065,14 +1021,12 @@ JanetTable *janet_core_env(JanetTable *replacements) {
"the dispatch function in the case of a new fiber. Returns either the return result of " "the dispatch function in the case of a new fiber. Returns either the return result of "
"the fiber's dispatch function, or the value from the next yield call in fiber.")); "the fiber's dispatch function, or the value from the next yield call in fiber."));
janet_quick_asm(env, JANET_FUN_IN, janet_quick_asm(env, JANET_FUN_IN,
"in", 3, 2, 3, 4, get_asm, sizeof(get_asm), "in", 3, 2, 3, 4, in_asm, sizeof(in_asm),
JDOC("(get ds key &opt dflt)\n\n" JDOC("(in ds key &opt dflt)\n\n"
"Get a value from any associative data structure. Arrays, tuples, tables, structs, strings, " "Get value in ds at key, works on associative data structures. Arrays, tuples, tables, structs, "
"symbols, and buffers are all associative and can be used with get. Order structures, name " "strings, symbols, and buffers are all associative and can be used. Arrays, tuples, strings, buffers, "
"arrays, tuples, strings, buffers, and symbols must use integer keys. Structs and tables can " "and symbols must use integer keys that are in bounds or an error is raised. Structs and tables can "
"take any value as a key except nil and return a value except nil. Byte sequences will return " "take any value as a key except nil and will return nil or dflt if not found."));
"integer representations of bytes as result of a get call. If no values is found, will return "
"dflt or nil if no default is provided."));
janet_quick_asm(env, JANET_FUN_PUT, janet_quick_asm(env, JANET_FUN_PUT,
"put", 3, 3, 3, 3, put_asm, sizeof(put_asm), "put", 3, 3, 3, 3, put_asm, sizeof(put_asm),
JDOC("(put ds key value)\n\n" JDOC("(put ds key value)\n\n"

View File

@ -49,13 +49,13 @@ static void int64_unmarshal(void *p, JanetMarshalContext *ctx) {
static void it_s64_tostring(void *p, JanetBuffer *buffer) { static void it_s64_tostring(void *p, JanetBuffer *buffer) {
char str[32]; char str[32];
sprintf(str, "<core/s64 %" PRId64 ">", *((int64_t *)p)); sprintf(str, "%" PRId64, *((int64_t *)p));
janet_buffer_push_cstring(buffer, str); janet_buffer_push_cstring(buffer, str);
} }
static void it_u64_tostring(void *p, JanetBuffer *buffer) { static void it_u64_tostring(void *p, JanetBuffer *buffer) {
char str[32]; char str[32];
sprintf(str, "<core/u64 %" PRIu64 ">", *((uint64_t *)p)); sprintf(str, "%" PRIu64, *((uint64_t *)p));
janet_buffer_push_cstring(buffer, str); janet_buffer_push_cstring(buffer, str);
} }

View File

@ -37,7 +37,12 @@
static void number_to_string_b(JanetBuffer *buffer, double x) { static void number_to_string_b(JanetBuffer *buffer, double x) {
janet_buffer_ensure(buffer, buffer->count + BUFSIZE, 2); janet_buffer_ensure(buffer, buffer->count + BUFSIZE, 2);
int count = snprintf((char *) buffer->data + buffer->count, BUFSIZE, "%g", x); /* Use int32_t range for valid integers because that is the
* range most integer-expecting functions in the C api use. */
const char *fmt = (x == floor(x) &&
x <= ((double) INT32_MAX) &&
x >= ((double) INT32_MIN)) ? "%.0f" : "%g";
int count = snprintf((char *) buffer->data + buffer->count, BUFSIZE, fmt, x);
buffer->count += count; buffer->count += count;
} }

View File

@ -207,6 +207,52 @@ Janet janet_get(Janet ds, Janet key) {
return value; return value;
} }
Janet janet_get_permissive(Janet ds, Janet key) {
JanetType t = janet_type(ds);
switch (t) {
default:
return janet_wrap_nil();
case JANET_STRING:
case JANET_SYMBOL:
case JANET_KEYWORD: {
if (!janet_checkint(key)) return janet_wrap_nil();
int32_t index = janet_unwrap_integer(key);
if (index < 0) return janet_wrap_nil();
const uint8_t *str = janet_unwrap_string(ds);
if (index >= janet_string_length(str)) return janet_wrap_nil();
return janet_wrap_integer(str[index]);
}
case JANET_ABSTRACT: {
void *abst = janet_unwrap_abstract(ds);
JanetAbstractType *type = (JanetAbstractType *)janet_abstract_type(abst);
if (!type->get) return janet_wrap_nil();
return (type->get)(abst, key);
}
case JANET_ARRAY:
case JANET_TUPLE: {
if (!janet_checkint(key)) return janet_wrap_nil();
int32_t index = janet_unwrap_integer(key);
if (index < 0) return janet_wrap_nil();
if (t == JANET_ARRAY) {
JanetArray *a = janet_unwrap_array(ds);
if (index >= a->count) return janet_wrap_nil();
return a->data[index];
} else {
const Janet *t = janet_unwrap_tuple(ds);
if (index >= janet_tuple_length(t)) return janet_wrap_nil();
return t[index];
}
}
case JANET_TABLE: {
return janet_table_get(janet_unwrap_table(ds), key);
}
case JANET_STRUCT: {
const JanetKV *st = janet_unwrap_struct(ds);
return janet_struct_get(st, key);
}
}
}
Janet janet_getindex(Janet ds, int32_t index) { Janet janet_getindex(Janet ds, int32_t index) {
Janet value; Janet value;
if (index < 0) janet_panic("expected non-negative index"); if (index < 0) janet_panic("expected non-negative index");

View File

@ -1319,6 +1319,7 @@ JANET_API int32_t janet_hash(Janet x);
JANET_API int janet_compare(Janet x, Janet y); JANET_API int janet_compare(Janet x, Janet y);
JANET_API int janet_cstrcmp(const uint8_t *str, const char *other); JANET_API int janet_cstrcmp(const uint8_t *str, const char *other);
JANET_API Janet janet_get(Janet ds, Janet key); JANET_API Janet janet_get(Janet ds, Janet key);
JANET_API Janet janet_get_permissive(Janet ds, Janet key);
JANET_API Janet janet_getindex(Janet ds, int32_t index); JANET_API Janet janet_getindex(Janet ds, int32_t index);
JANET_API int32_t janet_length(Janet x); JANET_API int32_t janet_length(Janet x);
JANET_API Janet janet_lengthv(Janet x); JANET_API Janet janet_lengthv(Janet x);

View File

@ -65,6 +65,9 @@
(assert (:== (:/ (u64 "0xffff_ffff_ffff_ffff") 8 2) "0xfffffffffffffff") "bigint operations") (assert (:== (:/ (u64 "0xffff_ffff_ffff_ffff") 8 2) "0xfffffffffffffff") "bigint operations")
(assert (let [a (u64 0xff)] (:== (:+ a a a a) (:* a 2 2))) "bigint operations") (assert (let [a (u64 0xff)] (:== (:+ a a a a) (:* a 2 2))) "bigint operations")
(assert (= (string (i64 -123)) "-123") "i64 prints reasonably")
(assert (= (string (u64 123)) "123") "u64 prints reasonably")
(assert-error (assert-error
"trap INT64_MIN / -1" "trap INT64_MIN / -1"
(:/ (int/s64 "-0x8000_0000_0000_0000") -1)) (:/ (int/s64 "-0x8000_0000_0000_0000") -1))