mirror of
https://github.com/janet-lang/janet
synced 2025-12-03 07:08:09 +00:00
Add errorhandling helper functions and macros for writing c functions.
This commit is contained in:
@@ -106,19 +106,22 @@ Dst dst_array_peek(DstArray *array) {
|
||||
/* C Functions */
|
||||
|
||||
static int cfun_pop(DstArgs args) {
|
||||
if (args.n != 1 || !dst_checktype(args.v[0], DST_ARRAY)) return dst_throw(args, "expected array");
|
||||
dst_fixarity(args, 1);
|
||||
dst_check(args, 0, DST_ARRAY);
|
||||
return dst_return(args, dst_array_pop(dst_unwrap_array(args.v[0])));
|
||||
}
|
||||
|
||||
static int cfun_peek(DstArgs args) {
|
||||
if (args.n != 1 || !dst_checktype(args.v[0], DST_ARRAY)) return dst_throw(args, "expected array");
|
||||
dst_fixarity(args, 1);
|
||||
dst_check(args, 0, DST_ARRAY);
|
||||
return dst_return(args, dst_array_peek(dst_unwrap_array(args.v[0])));
|
||||
}
|
||||
|
||||
static int cfun_push(DstArgs args) {
|
||||
DstArray *array;
|
||||
int32_t newcount;
|
||||
if (args.n < 1 || !dst_checktype(args.v[0], DST_ARRAY)) return dst_throw(args, "expected array");
|
||||
dst_minarity(args, 1);
|
||||
dst_check(args, 0, DST_ARRAY);
|
||||
array = dst_unwrap_array(args.v[0]);
|
||||
newcount = array->count - 1 + args.n;
|
||||
dst_array_ensure(array, newcount);
|
||||
@@ -129,8 +132,9 @@ static int cfun_push(DstArgs args) {
|
||||
|
||||
static int cfun_setcount(DstArgs args) {
|
||||
int32_t newcount;
|
||||
if (args.n != 2 || !dst_checktype(args.v[0], DST_ARRAY)) return dst_throw(args, "expected array");
|
||||
if (!dst_checktype(args.v[1], DST_INTEGER)) return dst_throw(args, "expected positive integer");
|
||||
dst_fixarity(args, 2);
|
||||
dst_check(args, 0, DST_ARRAY);
|
||||
dst_check(args, 1, DST_INTEGER);
|
||||
newcount = dst_unwrap_integer(args.v[1]);
|
||||
if (newcount < 0) return dst_throw(args, "expected positive integer");
|
||||
dst_array_setcount(dst_unwrap_array(args.v[0]), newcount);
|
||||
@@ -139,8 +143,9 @@ static int cfun_setcount(DstArgs args) {
|
||||
|
||||
static int cfun_ensure(DstArgs args) {
|
||||
int32_t newcount;
|
||||
if (args.n != 2 || !dst_checktype(args.v[0], DST_ARRAY)) return dst_throw(args, "expected array");
|
||||
if (!dst_checktype(args.v[1], DST_INTEGER)) return dst_throw(args, "expected positive integer");
|
||||
dst_fixarity(args, 2);
|
||||
dst_check(args, 0, DST_ARRAY);
|
||||
dst_check(args, 1, DST_INTEGER);
|
||||
newcount = dst_unwrap_integer(args.v[1]);
|
||||
if (newcount < 0) return dst_throw(args, "expected positive integer");
|
||||
dst_array_ensure(dst_unwrap_array(args.v[0]), newcount);
|
||||
@@ -152,7 +157,10 @@ static int cfun_slice(DstArgs args) {
|
||||
int32_t len;
|
||||
DstArray *ret;
|
||||
int32_t start, end;
|
||||
if (args.n < 1 || !dst_seq_view(args.v[0], &vals, &len)) return dst_throw(args, "expected array/tuple");
|
||||
dst_minarity(args, 1);
|
||||
dst_maxarity(args, 3);
|
||||
if (!dst_seq_view(args.v[0], &vals, &len))
|
||||
return dst_throw(args, "expected array|tuple");
|
||||
/* Get start */
|
||||
if (args.n < 2) {
|
||||
start = 0;
|
||||
@@ -187,7 +195,8 @@ static int cfun_slice(DstArgs args) {
|
||||
static int cfun_concat(DstArgs args) {
|
||||
int32_t i;
|
||||
DstArray *array;
|
||||
if (args.n < 1 || !dst_checktype(args.v[0], DST_ARRAY)) return dst_throw(args, "expected array");
|
||||
dst_minarity(args, 1);
|
||||
dst_check(args, 0, DST_ARRAY);
|
||||
array = dst_unwrap_array(args.v[0]);
|
||||
for (i = 1; i < args.n; i++) {
|
||||
switch (dst_type(args.v[i])) {
|
||||
|
||||
@@ -97,6 +97,10 @@ int dst_buffer_push_bytes(DstBuffer *buffer, const uint8_t *string, int32_t leng
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dst_buffer_push_string(DstBuffer *buffer, const uint8_t *string) {
|
||||
return dst_buffer_push_bytes(buffer, string, dst_string_length(string));
|
||||
}
|
||||
|
||||
/* Push a single byte to the buffer */
|
||||
int dst_buffer_push_u8(DstBuffer *buffer, uint8_t byte) {
|
||||
if (dst_buffer_extra(buffer, 1)) return -1;
|
||||
|
||||
@@ -127,7 +127,7 @@ int dst_core_struct(DstArgs args) {
|
||||
}
|
||||
|
||||
int dst_core_gensym(DstArgs args) {
|
||||
if (args.n > 1) return dst_throw(args, "expected one argument");
|
||||
dst_maxarity(args, 1);
|
||||
if (args.n == 0) {
|
||||
return dst_return(args, dst_wrap_symbol(dst_symbol_gen(NULL, 0)));
|
||||
} else {
|
||||
@@ -137,14 +137,14 @@ int dst_core_gensym(DstArgs args) {
|
||||
}
|
||||
|
||||
int dst_core_length(DstArgs args) {
|
||||
if (args.n != 1) return dst_throw(args, "expected at least 1 argument");
|
||||
dst_checkmany(args, 0, DST_TFLAG_LENGTHABLE);
|
||||
return dst_return(args, dst_wrap_integer(dst_length(args.v[0])));
|
||||
}
|
||||
|
||||
int dst_core_get(DstArgs args) {
|
||||
int32_t i;
|
||||
Dst ds;
|
||||
if (args.n < 1) return dst_throw(args, "expected at least 1 argument");
|
||||
dst_minarity(args, 1);
|
||||
ds = args.v[0];
|
||||
for (i = 1; i < args.n; i++) {
|
||||
ds = dst_get(ds, args.v[i]);
|
||||
@@ -155,15 +155,15 @@ int dst_core_get(DstArgs args) {
|
||||
}
|
||||
|
||||
int dst_core_rawget(DstArgs args) {
|
||||
if (args.n != 2) return dst_throw(args, "expected 2 arguments");
|
||||
if (!dst_checktype(args.v[0], DST_TABLE)) return dst_throw(args, "expected table");
|
||||
dst_fixarity(args, 2);
|
||||
dst_check(args, 0, DST_TABLE);
|
||||
return dst_return(args, dst_table_rawget(dst_unwrap_table(args.v[0]), args.v[1]));
|
||||
}
|
||||
|
||||
int dst_core_getproto(DstArgs args) {
|
||||
DstTable *t;
|
||||
if (args.n != 1) return dst_throw(args, "expected 1 argument");
|
||||
if (!dst_checktype(args.v[0], DST_TABLE)) return dst_throw(args, "expected table");
|
||||
dst_fixarity(args, 1);
|
||||
dst_check(args, 0, DST_TABLE);
|
||||
t = dst_unwrap_table(args.v[0]);
|
||||
return dst_return(args, t->proto
|
||||
? dst_wrap_table(t->proto)
|
||||
@@ -171,10 +171,9 @@ int dst_core_getproto(DstArgs args) {
|
||||
}
|
||||
|
||||
int dst_core_setproto(DstArgs args) {
|
||||
if (args.n != 2) return dst_throw(args, "expected 2 arguments");
|
||||
if (!dst_checktype(args.v[0], DST_TABLE)) return dst_throw(args, "expected table");
|
||||
if (!dst_checktype(args.v[1], DST_TABLE) && !dst_checktype(args.v[1], DST_NIL))
|
||||
return dst_throw(args, "expected table");
|
||||
dst_fixarity(args, 2);
|
||||
dst_check(args, 0, DST_TABLE);
|
||||
dst_checkmany(args, 1, DST_TFLAG_TABLE | DST_TFLAG_NIL);
|
||||
dst_unwrap_table(args.v[0])->proto = dst_checktype(args.v[1], DST_TABLE)
|
||||
? dst_unwrap_table(args.v[1])
|
||||
: NULL;
|
||||
@@ -184,7 +183,7 @@ int dst_core_setproto(DstArgs args) {
|
||||
int dst_core_put(DstArgs args) {
|
||||
Dst ds, key, value;
|
||||
DstArgs subargs = args;
|
||||
if (args.n < 3) return dst_throw(args, "expected at least 3 arguments");
|
||||
dst_minarity(args, 3);
|
||||
subargs.n -= 2;
|
||||
if (dst_core_get(subargs)) return 1;
|
||||
ds = *args.ret;
|
||||
@@ -201,20 +200,23 @@ int dst_core_gccollect(DstArgs args) {
|
||||
}
|
||||
|
||||
int dst_core_gcsetinterval(DstArgs args) {
|
||||
if (args.n < 1 ||
|
||||
!dst_checktype(args.v[0], DST_INTEGER) ||
|
||||
dst_unwrap_integer(args.v[0]) < 0)
|
||||
int32_t val;
|
||||
dst_fixarity(args, 1);
|
||||
dst_check(args, 0, DST_INTEGER);
|
||||
val = dst_unwrap_integer(args.v[0]);
|
||||
if (val < 0)
|
||||
return dst_throw(args, "expected non-negative integer");
|
||||
dst_vm_gc_interval = dst_unwrap_integer(args.v[0]);
|
||||
return dst_return(args, dst_wrap_integer(dst_vm_gc_interval));
|
||||
dst_vm_gc_interval = val;
|
||||
return dst_return(args, args.v[0]);
|
||||
}
|
||||
|
||||
int dst_core_gcinterval(DstArgs args) {
|
||||
dst_fixarity(args, 0);
|
||||
return dst_return(args, dst_wrap_integer(dst_vm_gc_interval));
|
||||
}
|
||||
|
||||
int dst_core_type(DstArgs args) {
|
||||
if (args.n != 1) return dst_throw(args, "expected 1 argument");
|
||||
dst_fixarity(args, 1);
|
||||
if (dst_checktype(args.v[0], DST_ABSTRACT)) {
|
||||
return dst_return(args, dst_csymbolv(dst_abstract_type(dst_unwrap_abstract(args.v[0]))->name));
|
||||
} else {
|
||||
@@ -225,20 +227,19 @@ int dst_core_type(DstArgs args) {
|
||||
int dst_core_next(DstArgs args) {
|
||||
Dst ds;
|
||||
const DstKV *kv;
|
||||
if (args.n != 2) return dst_throw(args, "expected 2 arguments");
|
||||
dst_fixarity(args, 2);
|
||||
dst_checkmany(args, 0, DST_TFLAG_DICTIONARY);
|
||||
ds = args.v[0];
|
||||
if (dst_checktype(ds, DST_TABLE)) {
|
||||
DstTable *t = dst_unwrap_table(ds);
|
||||
kv = dst_checktype(args.v[1], DST_NIL)
|
||||
? NULL
|
||||
: dst_table_find(t, args.v[1]);
|
||||
} else if (dst_checktype(ds, DST_STRUCT)) {
|
||||
} else {
|
||||
const DstKV *st = dst_unwrap_struct(ds);
|
||||
kv = dst_checktype(args.v[1], DST_NIL)
|
||||
? NULL
|
||||
: dst_struct_find(st, args.v[1]);
|
||||
} else {
|
||||
return dst_throw(args, "expected table/struct");
|
||||
}
|
||||
kv = dst_next(ds, kv);
|
||||
if (kv) {
|
||||
@@ -248,7 +249,7 @@ int dst_core_next(DstArgs args) {
|
||||
}
|
||||
|
||||
int dst_core_hash(DstArgs args) {
|
||||
if (args.n != 1) return dst_throw(args, "expected 1 argument");
|
||||
dst_fixarity(args, 1);
|
||||
return dst_return(args, dst_wrap_integer(dst_hash(args.v[0])));
|
||||
}
|
||||
|
||||
@@ -256,8 +257,10 @@ int dst_core_string_slice(DstArgs args) {
|
||||
const uint8_t *data;
|
||||
int32_t len, start, end;
|
||||
const uint8_t *ret;
|
||||
if (args.n < 1 || !dst_chararray_view(args.v[0], &data, &len))
|
||||
return dst_throw(args, "expected buffer/string");
|
||||
dst_minarity(args, 1);
|
||||
dst_maxarity(args, 3);
|
||||
if (!dst_chararray_view(args.v[0], &data, &len))
|
||||
return dst_throw(args, "expected buffer|string|symbol");
|
||||
/* Get start */
|
||||
if (args.n < 2) {
|
||||
start = 0;
|
||||
|
||||
@@ -205,3 +205,48 @@ int dst_hashtable_view(Dst tab, const DstKV **data, int32_t *len, int32_t *cap)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dst_type_err(DstArgs args, int32_t n, DstType expected) {
|
||||
DstType actual = n < args.n ? dst_type(args.v[n]) : DST_NIL;
|
||||
const uint8_t *message = dst_formatc(
|
||||
"bad argument #%d, expected %t, got %t",
|
||||
n,
|
||||
expected,
|
||||
actual);
|
||||
return dst_throwv(args, dst_wrap_string(message));
|
||||
}
|
||||
|
||||
int dst_typemany_err(DstArgs args, int32_t n, int expected) {
|
||||
int i;
|
||||
int first = 1;
|
||||
const uint8_t *message;
|
||||
DstType actual = n < args.n ? dst_type(args.v[n]) : DST_NIL;
|
||||
DstBuffer buf;
|
||||
dst_buffer_init(&buf, 20);
|
||||
dst_buffer_push_string(&buf, dst_formatc("bad argument #%d, expected ", n));
|
||||
i = 0;
|
||||
while (expected) {
|
||||
if (1 & expected) {
|
||||
if (first) {
|
||||
first = 0;
|
||||
} else {
|
||||
dst_buffer_push_u8(&buf, '|');
|
||||
}
|
||||
dst_buffer_push_cstring(&buf, dst_type_names[i] + 1);
|
||||
}
|
||||
i++;
|
||||
expected >>= 1;
|
||||
}
|
||||
dst_buffer_push_cstring(&buf, ", got ");
|
||||
dst_buffer_push_cstring(&buf, dst_type_names[actual] + 1);
|
||||
message = dst_string(buf.data, buf.count);
|
||||
dst_buffer_deinit(&buf);
|
||||
return dst_throwv(args, dst_wrap_string(message));
|
||||
}
|
||||
|
||||
int dst_arity_err(DstArgs args, int32_t n, const char *prefix) {
|
||||
return dst_throwv(args,
|
||||
dst_wrap_string(dst_formatc(
|
||||
"expected %s%d argument%s, got %d",
|
||||
prefix, n, n == 1 ? "" : "s", args.n)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user