1
0
mirror of https://github.com/janet-lang/janet synced 2025-06-19 23:14:15 +00:00

Update C API to use friendlier functions rather than macros.

Error handling is implemented with setjmp/longjmp so code
can be more concise. This required a very large but straight forward refactor for all
of the libraries.
This commit is contained in:
Calvin Rose 2019-01-05 20:09:03 -05:00
parent 5b62c8e6db
commit b60e3e302a
23 changed files with 1066 additions and 1534 deletions

View File

@ -118,135 +118,97 @@ Janet janet_array_peek(JanetArray *array) {
/* C Functions */ /* C Functions */
static int cfun_new(JanetArgs args) { static Janet cfun_new(int32_t argc, Janet *argv) {
int32_t cap; janet_arity(argc, 1, 1);
JanetArray *array; int32_t cap = janet_getinteger(argv, 0);
JANET_FIXARITY(args, 1); JanetArray *array = janet_array(cap);
JANET_ARG_INTEGER(cap, args, 0); return janet_wrap_array(array);
array = janet_array(cap);
JANET_RETURN_ARRAY(args, array);
} }
static int cfun_pop(JanetArgs args) { static Janet cfun_pop(int32_t argc, Janet *argv) {
JanetArray *array; janet_arity(argc, 1, 1);
JANET_FIXARITY(args, 1); JanetArray *array = janet_getarray(argv, 0);
JANET_ARG_ARRAY(array, args, 0); return janet_array_pop(array);
JANET_RETURN(args, janet_array_pop(array));
} }
static int cfun_peek(JanetArgs args) { static Janet cfun_peek(int32_t argc, Janet *argv) {
JanetArray *array; janet_arity(argc, 1, 1);
JANET_FIXARITY(args, 1); JanetArray *array = janet_getarray(argv, 0);
JANET_ARG_ARRAY(array, args, 0); return janet_array_peek(array);
JANET_RETURN(args, janet_array_peek(array));
} }
static int cfun_push(JanetArgs args) { static Janet cfun_push(int32_t argc, Janet *argv) {
JanetArray *array; janet_arity(argc, 1, -1);
int32_t newcount; JanetArray *array = janet_getarray(argv, 0);
JANET_MINARITY(args, 1); int32_t newcount = array->count - 1 + argc;
JANET_ARG_ARRAY(array, args, 0);
newcount = array->count - 1 + args.n;
janet_array_ensure(array, newcount, 2); janet_array_ensure(array, newcount, 2);
if (args.n > 1) memcpy(array->data + array->count, args.v + 1, (args.n - 1) * sizeof(Janet)); if (argc > 1) memcpy(array->data + array->count, argv + 1, (argc - 1) * sizeof(Janet));
array->count = newcount; array->count = newcount;
JANET_RETURN(args, args.v[0]); return argv[0];
} }
static int cfun_ensure(JanetArgs args) { static Janet cfun_ensure(int32_t argc, Janet *argv) {
JanetArray *array; janet_arity(argc, 3, 3);
int32_t newcount; JanetArray *array = janet_getarray(argv, 0);
int32_t growth; int32_t newcount = janet_getinteger(argv, 1);
JANET_FIXARITY(args, 3); int32_t growth = janet_getinteger(argv, 2);
JANET_ARG_ARRAY(array, args, 0); if (newcount < 1) janet_panic("expected positive integer");
JANET_ARG_INTEGER(newcount, args, 1);
JANET_ARG_INTEGER(growth, args, 2);
if (newcount < 0) JANET_THROW(args, "expected positive integer");
janet_array_ensure(array, newcount, growth); janet_array_ensure(array, newcount, growth);
JANET_RETURN(args, args.v[0]); return argv[0];
} }
static int cfun_slice(JanetArgs args) { static Janet cfun_slice(int32_t argc, Janet *argv) {
const Janet *vals; JanetRange range = janet_getslice(argc, argv);
int32_t len; JanetView view = janet_getindexed(argv, 0);
JanetArray *ret; JanetArray *array = janet_array(range.end - range.start);
int32_t start, end; memcpy(array->data, view.items + range.start, sizeof(Janet) * (range.end - range.start));
JANET_MINARITY(args, 1); array->count = range.end - range.start;
JANET_MAXARITY(args, 3); return janet_wrap_array(array);
if (!janet_indexed_view(args.v[0], &vals, &len))
JANET_THROW(args, "expected array|tuple");
/* Get start */
if (args.n < 2) {
start = 0;
} else {
JANET_ARG_INTEGER(start, args, 1);
}
/* Get end */
if (args.n < 3) {
end = -1;
} else {
JANET_ARG_INTEGER(end, args, 2);
}
if (start < 0) start = len + start;
if (end < 0) end = len + end + 1;
if (end < 0 || start < 0 || end > len || start > len)
JANET_THROW(args, "slice range out of bounds");
if (end >= start) {
ret = janet_array(end - start);
memcpy(ret->data, vals + start, sizeof(Janet) * (end - start));
ret->count = end - start;
} else {
ret = janet_array(0);
}
JANET_RETURN_ARRAY(args, ret);
} }
static int cfun_concat(JanetArgs args) { static Janet cfun_concat(int32_t argc, Janet *argv) {
int32_t i; int32_t i;
JanetArray *array; janet_arity(argc, 1, -1);
JANET_MINARITY(args, 1); JanetArray *array = janet_getarray(argv, 0);
JANET_ARG_ARRAY(array, args, 0); for (i = 1; i < argc; i++) {
for (i = 1; i < args.n; i++) { switch (janet_type(argv[i])) {
switch (janet_type(args.v[i])) {
default: default:
janet_array_push(array, args.v[i]); janet_array_push(array, argv[i]);
break; break;
case JANET_ARRAY: case JANET_ARRAY:
case JANET_TUPLE: case JANET_TUPLE:
{ {
int32_t j, len; int32_t j, len;
const Janet *vals; const Janet *vals;
janet_indexed_view(args.v[i], &vals, &len); janet_indexed_view(argv[i], &vals, &len);
for (j = 0; j < len; j++) for (j = 0; j < len; j++)
janet_array_push(array, vals[j]); janet_array_push(array, vals[j]);
} }
break; break;
} }
} }
JANET_RETURN_ARRAY(args, array); return janet_wrap_array(array);
} }
static int cfun_insert(JanetArgs args) { static Janet cfun_insert(int32_t argc, Janet *argv) {
int32_t at;
size_t chunksize, restsize; size_t chunksize, restsize;
JanetArray *array; janet_arity(argc, 2, -1);
JANET_MINARITY(args, 2); JanetArray *array = janet_getarray(argv, 0);
JANET_ARG_ARRAY(array, args, 0); int32_t at = janet_getinteger(argv, 1);
JANET_ARG_INTEGER(at, args, 1);
if (at < 0) { if (at < 0) {
at = array->count + at + 1; at = array->count + at + 1;
} }
if (at < 0 || at > array->count) if (at < 0 || at > array->count)
JANET_THROW(args, "insertion index out of bounds"); janet_panicf("insertion index %d out of range [0,%d]", at, array->count);
chunksize = (args.n - 2) * sizeof(Janet); chunksize = (argc - 2) * sizeof(Janet);
restsize = (array->count - at) * sizeof(Janet); restsize = (array->count - at) * sizeof(Janet);
janet_array_ensure(array, array->count + args.n - 2, 2); janet_array_ensure(array, array->count + argc - 2, 2);
memmove(array->data + at + args.n - 2, memmove(array->data + at + argc - 2,
array->data + at, array->data + at,
restsize); restsize);
memcpy(array->data + at, args.v + 2, chunksize); memcpy(array->data + at, argv + 2, chunksize);
array->count += (args.n - 2); array->count += (argc - 2);
JANET_RETURN_ARRAY(args, array); return janet_wrap_array(array);
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
@ -300,8 +262,6 @@ static const JanetReg cfuns[] = {
}; };
/* Load the array module */ /* Load the array module */
int janet_lib_array(JanetArgs args) { void janet_lib_array(JanetTable *env) {
JanetTable *env = janet_env(args);
janet_cfuns(env, NULL, cfuns); janet_cfuns(env, NULL, cfuns);
return 0;
} }

View File

@ -914,22 +914,20 @@ Janet janet_disasm(JanetFuncDef *def) {
} }
/* C Function for assembly */ /* C Function for assembly */
static int cfun_asm(JanetArgs args) { static Janet cfun_asm(int32_t argc, Janet *argv) {
janet_arity(argc, 1, 1);
JanetAssembleResult res; JanetAssembleResult res;
JANET_FIXARITY(args, 1); res = janet_asm(argv[0], 0);
res = janet_asm(args.v[0], 0); if (res.status != JANET_ASSEMBLE_OK) {
if (res.status == JANET_ASSEMBLE_OK) { janet_panics(res.error);
JANET_RETURN_FUNCTION(args, janet_thunk(res.funcdef));
} else {
JANET_THROWV(args, janet_wrap_string(res.error));
} }
return janet_wrap_function(janet_thunk(res.funcdef));
} }
static int cfun_disasm(JanetArgs args) { static Janet cfun_disasm(int32_t argc, Janet *argv) {
JanetFunction *f; janet_arity(argc, 1, 1);
JANET_FIXARITY(args, 1); JanetFunction *f = janet_getfunction(argv, 0);
JANET_ARG_FUNCTION(f, args, 0); return janet_disasm(f->def);
JANET_RETURN(args, janet_disasm(f->def));
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
@ -949,10 +947,8 @@ static const JanetReg cfuns[] = {
}; };
/* Load the library */ /* Load the library */
int janet_lib_asm(JanetArgs args) { void janet_lib_asm(JanetTable *env) {
JanetTable *env = janet_env(args);
janet_cfuns(env, NULL, cfuns); janet_cfuns(env, NULL, cfuns);
return 0;
} }
#endif #endif

View File

@ -77,10 +77,10 @@ void janet_buffer_setcount(JanetBuffer *buffer, int32_t count) {
/* Adds capacity for enough extra bytes to the buffer. Ensures that the /* Adds capacity for enough extra bytes to the buffer. Ensures that the
* next n bytes pushed to the buffer will not cause a reallocation */ * next n bytes pushed to the buffer will not cause a reallocation */
int janet_buffer_extra(JanetBuffer *buffer, int32_t n) { void janet_buffer_extra(JanetBuffer *buffer, int32_t n) {
/* Check for buffer overflow */ /* Check for buffer overflow */
if ((int64_t)n + buffer->count > INT32_MAX) { if ((int64_t)n + buffer->count > INT32_MAX) {
return -1; janet_panic("buffer overflow");
} }
int32_t new_size = buffer->count + n; int32_t new_size = buffer->count + n;
if (new_size > buffer->capacity) { if (new_size > buffer->capacity) {
@ -92,59 +92,54 @@ int janet_buffer_extra(JanetBuffer *buffer, int32_t n) {
buffer->data = new_data; buffer->data = new_data;
buffer->capacity = new_capacity; buffer->capacity = new_capacity;
} }
return 0;
} }
/* Push a cstring to buffer */ /* Push a cstring to buffer */
int janet_buffer_push_cstring(JanetBuffer *buffer, const char *cstring) { void janet_buffer_push_cstring(JanetBuffer *buffer, const char *cstring) {
int32_t len = 0; int32_t len = 0;
while (cstring[len]) ++len; while (cstring[len]) ++len;
return janet_buffer_push_bytes(buffer, (const uint8_t *) cstring, len); janet_buffer_push_bytes(buffer, (const uint8_t *) cstring, len);
} }
/* Push multiple bytes into the buffer */ /* Push multiple bytes into the buffer */
int janet_buffer_push_bytes(JanetBuffer *buffer, const uint8_t *string, int32_t length) { void janet_buffer_push_bytes(JanetBuffer *buffer, const uint8_t *string, int32_t length) {
if (janet_buffer_extra(buffer, length)) return -1; janet_buffer_extra(buffer, length);
memcpy(buffer->data + buffer->count, string, length); memcpy(buffer->data + buffer->count, string, length);
buffer->count += length; buffer->count += length;
return 0;
} }
int janet_buffer_push_string(JanetBuffer *buffer, const uint8_t *string) { void janet_buffer_push_string(JanetBuffer *buffer, const uint8_t *string) {
return janet_buffer_push_bytes(buffer, string, janet_string_length(string)); janet_buffer_push_bytes(buffer, string, janet_string_length(string));
} }
/* Push a single byte to the buffer */ /* Push a single byte to the buffer */
int janet_buffer_push_u8(JanetBuffer *buffer, uint8_t byte) { void janet_buffer_push_u8(JanetBuffer *buffer, uint8_t byte) {
if (janet_buffer_extra(buffer, 1)) return -1; janet_buffer_extra(buffer, 1);
buffer->data[buffer->count] = byte; buffer->data[buffer->count] = byte;
buffer->count++; buffer->count++;
return 0;
} }
/* Push a 16 bit unsigned integer to the buffer */ /* Push a 16 bit unsigned integer to the buffer */
int janet_buffer_push_u16(JanetBuffer *buffer, uint16_t x) { void janet_buffer_push_u16(JanetBuffer *buffer, uint16_t x) {
if (janet_buffer_extra(buffer, 2)) return -1; janet_buffer_extra(buffer, 2);
buffer->data[buffer->count] = x & 0xFF; buffer->data[buffer->count] = x & 0xFF;
buffer->data[buffer->count + 1] = (x >> 8) & 0xFF; buffer->data[buffer->count + 1] = (x >> 8) & 0xFF;
buffer->count += 2; buffer->count += 2;
return 0;
} }
/* Push a 32 bit unsigned integer to the buffer */ /* Push a 32 bit unsigned integer to the buffer */
int janet_buffer_push_u32(JanetBuffer *buffer, uint32_t x) { void janet_buffer_push_u32(JanetBuffer *buffer, uint32_t x) {
if (janet_buffer_extra(buffer, 4)) return -1; janet_buffer_extra(buffer, 4);
buffer->data[buffer->count] = x & 0xFF; buffer->data[buffer->count] = x & 0xFF;
buffer->data[buffer->count + 1] = (x >> 8) & 0xFF; buffer->data[buffer->count + 1] = (x >> 8) & 0xFF;
buffer->data[buffer->count + 2] = (x >> 16) & 0xFF; buffer->data[buffer->count + 2] = (x >> 16) & 0xFF;
buffer->data[buffer->count + 3] = (x >> 24) & 0xFF; buffer->data[buffer->count + 3] = (x >> 24) & 0xFF;
buffer->count += 4; buffer->count += 4;
return 0;
} }
/* Push a 64 bit unsigned integer to the buffer */ /* Push a 64 bit unsigned integer to the buffer */
int janet_buffer_push_u64(JanetBuffer *buffer, uint64_t x) { void janet_buffer_push_u64(JanetBuffer *buffer, uint64_t x) {
if (janet_buffer_extra(buffer, 8)) return -1; janet_buffer_extra(buffer, 8);
buffer->data[buffer->count] = x & 0xFF; buffer->data[buffer->count] = x & 0xFF;
buffer->data[buffer->count + 1] = (x >> 8) & 0xFF; buffer->data[buffer->count + 1] = (x >> 8) & 0xFF;
buffer->data[buffer->count + 2] = (x >> 16) & 0xFF; buffer->data[buffer->count + 2] = (x >> 16) & 0xFF;
@ -154,118 +149,79 @@ int janet_buffer_push_u64(JanetBuffer *buffer, uint64_t x) {
buffer->data[buffer->count + 6] = (x >> 48) & 0xFF; buffer->data[buffer->count + 6] = (x >> 48) & 0xFF;
buffer->data[buffer->count + 7] = (x >> 56) & 0xFF; buffer->data[buffer->count + 7] = (x >> 56) & 0xFF;
buffer->count += 8; buffer->count += 8;
return 0;
} }
/* C functions */ /* C functions */
static int cfun_new(JanetArgs args) { static Janet cfun_new(int32_t argc, Janet *argv) {
int32_t cap; janet_arity(argc, 1, 1);
JanetBuffer *buffer; int32_t cap = janet_getinteger(argv, 0);
JANET_FIXARITY(args, 1); JanetBuffer *buffer = janet_buffer(cap);
JANET_ARG_INTEGER(cap, args, 0); return janet_wrap_buffer(buffer);
buffer = janet_buffer(cap);
JANET_RETURN_BUFFER(args, buffer);
} }
static int cfun_u8(JanetArgs args) { static Janet cfun_u8(int32_t argc, Janet *argv) {
int32_t i; int32_t i;
JanetBuffer *buffer; janet_arity(argc, 1, -1);
JANET_MINARITY(args, 1); JanetBuffer *buffer = janet_getbuffer(argv, 0);
JANET_ARG_BUFFER(buffer, args, 0); for (i = 1; i < argc; i++) {
for (i = 1; i < args.n; i++) { janet_buffer_push_u8(buffer, (uint8_t) (janet_getinteger(argv, i) & 0xFF));
int32_t integer;
JANET_ARG_INTEGER(integer, args, i);
if (janet_buffer_push_u8(buffer, (uint8_t) (integer & 0xFF)))
JANET_THROW(args, "buffer overflow");
} }
JANET_RETURN(args, args.v[0]); return argv[0];
} }
static int cfun_word(JanetArgs args) { static Janet cfun_word(int32_t argc, Janet *argv) {
int32_t i; int32_t i;
JanetBuffer *buffer; janet_arity(argc, 1, -1);
JANET_MINARITY(args, 1); JanetBuffer *buffer = janet_getbuffer(argv, 0);
JANET_ARG_BUFFER(buffer, args, 0); for (i = 1; i < argc; i++) {
for (i = 1; i < args.n; i++) { double number = janet_getnumber(argv, 0);
double number; uint32_t word = (uint32_t) number;
uint32_t word; if (word != number)
JANET_ARG_NUMBER(number, args, i); janet_panicf("cannot convert %v to machine word", argv[0]);
word = (uint32_t) number; janet_buffer_push_u32(buffer, word);
if (number != word) JANET_THROW(args, "cannot convert number to machine word");
if (janet_buffer_push_u32(buffer, word))
JANET_THROW(args, "buffer overflow");
} }
JANET_RETURN(args, args.v[0]); return argv[0];
} }
static int cfun_chars(JanetArgs args) { static Janet cfun_chars(int32_t argc, Janet *argv) {
int32_t i; int32_t i;
JanetBuffer *buffer; janet_arity(argc, 1, -1);
JANET_MINARITY(args, 1); JanetBuffer *buffer = janet_getbuffer(argv, 0);
JANET_ARG_BUFFER(buffer, args, 0); for (i = 1; i < argc; i++) {
for (i = 1; i < args.n; i++) { JanetByteView view = janet_getbytes(argv, i);
int32_t len; janet_buffer_push_bytes(buffer, view.bytes, view.len);
const uint8_t *str;
JANET_ARG_BYTES(str, len, args, i);
if (janet_buffer_push_bytes(buffer, str, len))
JANET_THROW(args, "buffer overflow");
} }
JANET_RETURN(args, args.v[0]); return argv[0];
} }
static int cfun_clear(JanetArgs args) { static Janet cfun_clear(int32_t argc, Janet *argv) {
JanetBuffer *buffer; janet_arity(argc, 1, 1);
JANET_FIXARITY(args, 1); JanetBuffer *buffer = janet_getbuffer(argv, 0);
JANET_ARG_BUFFER(buffer, args, 0);
buffer->count = 0; buffer->count = 0;
JANET_RETURN(args, args.v[0]); return argv[0];
} }
static int cfun_popn(JanetArgs args) { static Janet cfun_popn(int32_t argc, Janet *argv) {
JanetBuffer *buffer; janet_arity(argc, 2, 2);
int32_t n; JanetBuffer *buffer = janet_getbuffer(argv, 0);
JANET_FIXARITY(args, 2); int32_t n = janet_getinteger(argv, 1);
JANET_ARG_BUFFER(buffer, args, 0); if (n < 0) janet_panic("n must be non-negative");
JANET_ARG_INTEGER(n, args, 1);
if (n < 0) JANET_THROW(args, "n must be non-negative");
if (buffer->count < n) { if (buffer->count < n) {
buffer->count = 0; buffer->count = 0;
} else { } else {
buffer->count -= n; buffer->count -= n;
} }
JANET_RETURN(args, args.v[0]); return argv[0];
} }
static int cfun_slice(JanetArgs args) { static Janet cfun_slice(int32_t argc, Janet *argv) {
const uint8_t *data; JanetRange range = janet_getslice(argc, argv);
int32_t len, start, end; JanetByteView view = janet_getbytes(argv, 0);
JanetBuffer *ret; JanetBuffer *buffer = janet_buffer(range.end - range.start);
JANET_ARG_BYTES(data, len, args, 0); memcpy(buffer->data, view.bytes + range.start, range.end - range.start);
/* Get start */ buffer->count = range.end - range.start;
if (args.n < 2) { return janet_wrap_buffer(buffer);
start = 0;
} else {
JANET_ARG_INTEGER(start, args, 1);
}
/* Get end */
if (args.n < 3) {
end = -1;
} else {
JANET_ARG_INTEGER(end, args, 2);
}
if (start < 0) start = len + start;
if (end < 0) end = len + end + 1;
if (end < 0 || start < 0 || end > len || start > len)
JANET_THROW(args, "slice range out of bounds");
if (end >= start) {
ret = janet_buffer(end - start);
memcpy(ret->data, data + start, end - start);
ret->count = end - start;
} else {
ret = janet_buffer(0);
}
JANET_RETURN_BUFFER(args, ret);
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
@ -310,8 +266,6 @@ static const JanetReg cfuns[] = {
{NULL, NULL, NULL} {NULL, NULL, NULL}
}; };
int janet_lib_buffer(JanetArgs args) { void janet_lib_buffer(JanetTable *env) {
JanetTable *env = janet_env(args);
janet_cfuns(env, NULL, cfuns); janet_cfuns(env, NULL, cfuns);
return 0;
} }

View File

@ -43,5 +43,141 @@ void janet_panics(const uint8_t *message) {
} }
void janet_panic_type(Janet x, int32_t n, int expected) { void janet_panic_type(Janet x, int32_t n, int expected) {
janet_panicf("bad slot #%d, expected %T, got %t", n, expected, janet_type(x)); janet_panicf("bad slot #%d, expected %T, got %v", n, expected, x);
}
void janet_panic_abstract(Janet x, int32_t n, const JanetAbstractType *at) {
janet_panicf("bad slot #%d, expected %s, got %v", n, at->name, x);
}
void janet_arity(int32_t arity, int32_t min, int32_t max) {
if (min >= 0 && arity < min)
janet_panicf("arity mismatch, expected at least %d, got %d", min, arity);
if (max >= 0 && arity > max)
janet_panicf("arity mismatch, expected at most %d, got %d", max, arity);
}
#define DEFINE_GETTER(name, NAME, type) \
type janet_get##name(const Janet *argv, int32_t n) { \
Janet x = argv[n]; \
if (!janet_checktype(x, JANET_##NAME)) { \
janet_panic_type(x, n, JANET_TFLAG_##NAME); \
} \
return janet_unwrap_##name(x); \
}
DEFINE_GETTER(number, NUMBER, double)
DEFINE_GETTER(array, ARRAY, JanetArray *)
DEFINE_GETTER(tuple, TUPLE, const Janet *)
DEFINE_GETTER(table, TABLE, JanetTable *)
DEFINE_GETTER(struct, STRUCT, const JanetKV *)
DEFINE_GETTER(string, STRING, const uint8_t *)
DEFINE_GETTER(keyword, KEYWORD, const uint8_t *)
DEFINE_GETTER(symbol, SYMBOL, const uint8_t *)
DEFINE_GETTER(buffer, BUFFER, JanetBuffer *)
DEFINE_GETTER(fiber, FIBER, JanetFiber *)
DEFINE_GETTER(function, FUNCTION, JanetFunction *)
DEFINE_GETTER(cfunction, CFUNCTION, JanetCFunction)
int janet_getboolean(const Janet *argv, int32_t n) {
Janet x = argv[n];
if (janet_checktype(x, JANET_TRUE)) {
return 1;
} else if (!janet_checktype(x, JANET_FALSE)) {
janet_panicf("bad slot #%d, expected boolean, got %v", n, x);
}
return 0;
}
int32_t janet_getinteger(const Janet *argv, int32_t n) {
Janet x = argv[n];
if (!janet_checkint(x)) {
janet_panicf("bad slot #%d, expected integer, got %v", n, x);
}
return janet_unwrap_integer(x);
}
int64_t janet_getinteger64(const Janet *argv, int32_t n) {
Janet x = argv[n];
if (!janet_checkint64(x)) {
janet_panicf("bad slot #%d, expected 64 bit integer, got %v", n, x);
}
return (int64_t) janet_unwrap_number(x);
}
JanetView janet_getindexed(const Janet *argv, int32_t n) {
Janet x = argv[n];
JanetView view;
if (!janet_indexed_view(x, &view.items, &view.len)) {
janet_panic_type(x, n, JANET_TFLAG_INDEXED);
}
return view;
}
JanetByteView janet_getbytes(const Janet *argv, int32_t n) {
Janet x = argv[n];
JanetByteView view;
if (!janet_bytes_view(x, &view.bytes, &view.len)) {
janet_panic_type(x, n, JANET_TFLAG_BYTES);
}
return view;
}
JanetDictView janet_getdictionary(const Janet *argv, int32_t n) {
Janet x = argv[n];
JanetDictView view;
if (!janet_dictionary_view(x, &view.kvs, &view.len, &view.cap)) {
janet_panic_type(x, n, JANET_TFLAG_DICTIONARY);
}
return view;
}
void *janet_getabstract(const Janet *argv, int32_t n, const JanetAbstractType *at) {
Janet x = argv[n];
if (!janet_checktype(x, JANET_ABSTRACT)) {
janet_panic_abstract(x, n, at);
}
void *abstractx = janet_unwrap_abstract(x);
if (janet_abstract_type(abstractx) != at) {
janet_panic_abstract(x, n, at);
}
return abstractx;
}
JanetRange janet_getslice(int32_t argc, const Janet *argv) {
janet_arity(argc, 1, 3);
JanetRange range;
int32_t length = janet_length(argv[0]);
if (argc == 1) {
range.start = 0;
range.end = length;
} else if (argc == 2) {
range.start = janet_getinteger(argv, 1);
range.end = length;
if (range.start < 0) {
range.start += length + 1;
}
if (range.start < 0 || range.start > length) {
janet_panicf("slice start: index %d out of range [0,%d]", range.start, length);
}
} else if (argc == 3) {
range.start = janet_getinteger(argv, 1);
range.end = janet_getinteger(argv, 2);
if (range.start < 0) {
range.start += length + 1;
}
if (range.end < 0) {
range.end += length + 1;
}
if (range.start < 0 || range.start > length) {
janet_panicf("slice start: index %d out of range [0,%d]", range.start, length);
}
if (range.end < 0 || range.end > length) {
janet_panicf("slice end: index %d out of range [0,%d]", range.end, length);
}
if (range.end < range.start) {
range.end = range.start;
}
}
return range;
} }

View File

@ -699,29 +699,25 @@ JanetCompileResult janet_compile(Janet source, JanetTable *env, const uint8_t *w
} }
/* C Function for compiling */ /* C Function for compiling */
static int cfun(JanetArgs args) { static Janet cfun(int32_t argc, Janet *argv) {
JanetCompileResult res; janet_arity(argc, 2, 3);
JanetTable *t; JanetTable *env = janet_gettable(argv, 1);
JanetTable *env;
JANET_MINARITY(args, 2);
JANET_MAXARITY(args, 3);
JANET_ARG_TABLE(env, args, 1);
const uint8_t *source = NULL; const uint8_t *source = NULL;
if (args.n == 3) { if (argc == 3) {
JANET_ARG_STRING(source, args, 2); source = janet_getstring(argv, 2);
} }
res = janet_compile(args.v[0], env, source); JanetCompileResult res = janet_compile(argv[0], env, source);
if (res.status == JANET_COMPILE_OK) { if (res.status == JANET_COMPILE_OK) {
JANET_RETURN_FUNCTION(args, janet_thunk(res.funcdef)); return janet_wrap_function(janet_thunk(res.funcdef));
} else { } else {
t = janet_table(4); JanetTable *t = janet_table(4);
janet_table_put(t, janet_ckeywordv("error"), janet_wrap_string(res.error)); janet_table_put(t, janet_ckeywordv("error"), janet_wrap_string(res.error));
janet_table_put(t, janet_ckeywordv("start"), janet_wrap_integer(res.error_mapping.start)); janet_table_put(t, janet_ckeywordv("start"), janet_wrap_integer(res.error_mapping.start));
janet_table_put(t, janet_ckeywordv("end"), janet_wrap_integer(res.error_mapping.end)); janet_table_put(t, janet_ckeywordv("end"), janet_wrap_integer(res.error_mapping.end));
if (res.macrofiber) { if (res.macrofiber) {
janet_table_put(t, janet_ckeywordv("fiber"), janet_wrap_fiber(res.macrofiber)); janet_table_put(t, janet_ckeywordv("fiber"), janet_wrap_fiber(res.macrofiber));
} }
JANET_RETURN_TABLE(args, t); return janet_wrap_table(t);
} }
} }
@ -736,8 +732,6 @@ static const JanetReg cfuns[] = {
{NULL, NULL, NULL} {NULL, NULL, NULL}
}; };
int janet_lib_compile(JanetArgs args) { void janet_lib_compile(JanetTable *env) {
JanetTable *env = janet_env(args);
janet_cfuns(env, NULL, cfuns); janet_cfuns(env, NULL, cfuns);
return 0;
} }

View File

@ -1451,7 +1451,7 @@ value, one key will be ignored."
env) env)
(defn status-pp (defn status-pp
"Pretty print a signal and asscoaited state. Can be used as the "Pretty print a signal and associated state. Can be used as the
onsignal argument to run-context." onsignal argument to run-context."
[sig x f source] [sig x f source]
(def title (def title

View File

@ -50,14 +50,14 @@ typedef void *Clib;
#define error_clib() dlerror() #define error_clib() dlerror()
#endif #endif
JanetCFunction janet_native(const char *name, const uint8_t **error) { JanetModule janet_native(const char *name, const uint8_t **error) {
Clib lib = load_clib(name); Clib lib = load_clib(name);
JanetCFunction init; JanetModule init;
if (!lib) { if (!lib) {
*error = janet_cstring(error_clib()); *error = janet_cstring(error_clib());
return NULL; return NULL;
} }
init = (JanetCFunction) symbol_clib(lib, "_janet_init"); init = (JanetModule) symbol_clib(lib, "_janet_init");
if (!init) { if (!init) {
*error = janet_cstring("could not find _janet_init symbol"); *error = janet_cstring("could not find _janet_init symbol");
return NULL; return NULL;
@ -65,217 +65,205 @@ JanetCFunction janet_native(const char *name, const uint8_t **error) {
return init; return init;
} }
static int janet_core_native(JanetArgs args) { static Janet janet_core_native(int32_t argc, Janet *argv) {
JanetCFunction init; JanetModule init;
JanetTable *env = janet_table(0);
janet_arity(argc, 1, 1);
const uint8_t *path = janet_getstring(argv, 0);
const uint8_t *error = NULL; const uint8_t *error = NULL;
const uint8_t *path = NULL;
JANET_FIXARITY(args, 1);
JANET_ARG_STRING(path, args, 0);
init = janet_native((const char *)path, &error); init = janet_native((const char *)path, &error);
if (!init) { if (!init) {
JANET_THROWV(args, janet_wrap_string(error)); janet_panicf("could not load native %S: %S", path, error);
} }
JANET_RETURN_CFUNCTION(args, init); init(env);
return janet_wrap_table(env);
} }
static int janet_core_print(JanetArgs args) { static Janet janet_core_print(int32_t argc, Janet *argv) {
int32_t i; for (int32_t i = 0; i < argc; ++i) {
for (i = 0; i < args.n; ++i) {
int32_t j, len; int32_t j, len;
const uint8_t *vstr = janet_to_string(args.v[i]); const uint8_t *vstr = janet_to_string(argv[i]);
len = janet_string_length(vstr); len = janet_string_length(vstr);
for (j = 0; j < len; ++j) { for (j = 0; j < len; ++j) {
putc(vstr[j], stdout); putc(vstr[j], stdout);
} }
} }
putc('\n', stdout); putc('\n', stdout);
JANET_RETURN_NIL(args); return janet_wrap_nil();
} }
static int janet_core_describe(JanetArgs args) { static Janet janet_core_describe(int32_t argc, Janet *argv) {
int32_t i;
JanetBuffer b; JanetBuffer b;
janet_buffer_init(&b, 0); janet_buffer_init(&b, 0);
for (i = 0; i < args.n; ++i) { for (int32_t i = 0; i < argc; ++i) {
int32_t len; int32_t len;
const uint8_t *str = janet_description(args.v[i]); const uint8_t *str = janet_description(argv[i]);
len = janet_string_length(str); len = janet_string_length(str);
janet_buffer_push_bytes(&b, str, len); janet_buffer_push_bytes(&b, str, len);
} }
*args.ret = janet_stringv(b.data, b.count); Janet ret = janet_stringv(b.data, b.count);
janet_buffer_deinit(&b); janet_buffer_deinit(&b);
return 0; return ret;
} }
static int janet_core_string(JanetArgs args) { static Janet janet_core_string(int32_t argc, Janet *argv) {
int32_t i;
JanetBuffer b; JanetBuffer b;
janet_buffer_init(&b, 0); janet_buffer_init(&b, 0);
for (i = 0; i < args.n; ++i) { for (int32_t i = 0; i < argc; ++i) {
int32_t len; int32_t len;
const uint8_t *str = janet_to_string(args.v[i]); const uint8_t *str = janet_to_string(argv[i]);
len = janet_string_length(str); len = janet_string_length(str);
janet_buffer_push_bytes(&b, str, len); janet_buffer_push_bytes(&b, str, len);
} }
*args.ret = janet_stringv(b.data, b.count); Janet ret = janet_stringv(b.data, b.count);
janet_buffer_deinit(&b); janet_buffer_deinit(&b);
return 0; return ret;
} }
static int janet_core_symbol(JanetArgs args) { static Janet janet_core_symbol(int32_t argc, Janet *argv) {
int32_t i; int32_t i;
JanetBuffer b; JanetBuffer b;
janet_buffer_init(&b, 0); janet_buffer_init(&b, 0);
for (i = 0; i < args.n; ++i) { for (i = 0; i < argc; ++i) {
int32_t len; int32_t len;
const uint8_t *str = janet_to_string(args.v[i]); const uint8_t *str = janet_to_string(argv[i]);
len = janet_string_length(str); len = janet_string_length(str);
janet_buffer_push_bytes(&b, str, len); janet_buffer_push_bytes(&b, str, len);
} }
*args.ret = janet_symbolv(b.data, b.count); Janet ret = janet_symbolv(b.data, b.count);
janet_buffer_deinit(&b); janet_buffer_deinit(&b);
return 0; return ret;
} }
static int janet_core_keyword(JanetArgs args) { static Janet janet_core_keyword(int32_t argc, Janet *argv) {
int32_t i; int32_t i;
JanetBuffer b; JanetBuffer b;
janet_buffer_init(&b, 0); janet_buffer_init(&b, 0);
for (i = 0; i < args.n; ++i) { for (i = 0; i < argc; ++i) {
int32_t len; int32_t len;
const uint8_t *str = janet_to_string(args.v[i]); const uint8_t *str = janet_to_string(argv[i]);
len = janet_string_length(str); len = janet_string_length(str);
janet_buffer_push_bytes(&b, str, len); janet_buffer_push_bytes(&b, str, len);
} }
*args.ret = janet_keywordv(b.data, b.count); Janet ret = janet_keywordv(b.data, b.count);
janet_buffer_deinit(&b); janet_buffer_deinit(&b);
return 0; return ret;
} }
static int janet_core_buffer(JanetArgs args) { static Janet janet_core_buffer(int32_t argc, Janet *argv) {
int32_t i; int32_t i;
JanetBuffer *b = janet_buffer(0); JanetBuffer *b = janet_buffer(0);
for (i = 0; i < args.n; ++i) { for (i = 0; i < argc; ++i) {
int32_t len; int32_t len;
const uint8_t *str = janet_to_string(args.v[i]); const uint8_t *str = janet_to_string(argv[i]);
len = janet_string_length(str); len = janet_string_length(str);
janet_buffer_push_bytes(b, str, len); janet_buffer_push_bytes(b, str, len);
} }
JANET_RETURN_BUFFER(args, b); return janet_wrap_buffer(b);
} }
static int janet_core_is_abstract(JanetArgs args) { static Janet janet_core_is_abstract(int32_t argc, Janet *argv) {
JANET_FIXARITY(args, 1); janet_arity(argc, 1, 1);
JANET_RETURN_BOOLEAN(args, janet_checktype(args.v[0], JANET_ABSTRACT)); return janet_wrap_boolean(janet_checktype(argv[0], JANET_ABSTRACT));
} }
static int janet_core_scannumber(JanetArgs args) { static Janet janet_core_scannumber(int32_t argc, Janet *argv) {
const uint8_t *data; double number;
double val; janet_arity(argc, 1, 1);
int32_t len; JanetByteView view = janet_getbytes(argv, 1);
JANET_FIXARITY(args, 1); if (janet_scan_number(view.bytes, view.len, &number))
JANET_ARG_BYTES(data, len, args, 0); return janet_wrap_nil();
if (janet_scan_number(data, len, &val)) return janet_wrap_number(number);
JANET_THROW(args, "failed to scan number");
JANET_RETURN_NUMBER(args, val);
} }
static int janet_core_tuple(JanetArgs args) { static Janet janet_core_tuple(int32_t argc, Janet *argv) {
JANET_RETURN_TUPLE(args, janet_tuple_n(args.v, args.n)); return janet_wrap_tuple(janet_tuple_n(argv, argc));
} }
static int janet_core_array(JanetArgs args) { static Janet janet_core_array(int32_t argc, Janet *argv) {
JanetArray *array = janet_array(args.n); JanetArray *array = janet_array(argc);
array->count = args.n; array->count = argc;
memcpy(array->data, args.v, args.n * sizeof(Janet)); memcpy(array->data, argv, argc * sizeof(Janet));
JANET_RETURN_ARRAY(args, array); return janet_wrap_array(array);
} }
static int janet_core_table(JanetArgs args) { static Janet janet_core_table(int32_t argc, Janet *argv) {
int32_t i; int32_t i;
JanetTable *table = janet_table(args.n >> 1); if (argc & 1)
if (args.n & 1) janet_panic("expected even number of arguments");
JANET_THROW(args, "expected even number of arguments"); JanetTable *table = janet_table(argc >> 1);
for (i = 0; i < args.n; i += 2) { for (i = 0; i < argc; i += 2) {
janet_table_put(table, args.v[i], args.v[i + 1]); janet_table_put(table, argv[i], argv[i + 1]);
} }
JANET_RETURN_TABLE(args, table); return janet_wrap_table(table);
} }
static int janet_core_struct(JanetArgs args) { static Janet janet_core_struct(int32_t argc, Janet *argv) {
int32_t i; int32_t i;
JanetKV *st = janet_struct_begin(args.n >> 1); if (argc & 1)
if (args.n & 1) janet_panic("expected even number of arguments");
JANET_THROW(args, "expected even number of arguments"); JanetKV *st = janet_struct_begin(argc >> 1);
for (i = 0; i < args.n; i += 2) { for (i = 0; i < argc; i += 2) {
janet_struct_put(st, args.v[i], args.v[i + 1]); janet_struct_put(st, argv[i], argv[i + 1]);
} }
JANET_RETURN_STRUCT(args, janet_struct_end(st)); return janet_wrap_struct(janet_struct_end(st));
} }
static int janet_core_gensym(JanetArgs args) { static Janet janet_core_gensym(int32_t argc, Janet *argv) {
JANET_FIXARITY(args, 0); (void) argv;
JANET_RETURN_SYMBOL(args, janet_symbol_gen()); janet_arity(argc, 0, 0);
return janet_wrap_symbol(janet_symbol_gen());
} }
static int janet_core_gccollect(JanetArgs args) { static Janet janet_core_gccollect(int32_t argc, Janet *argv) {
(void) args; (void) argv;
(void) argc;
janet_collect(); janet_collect();
return 0; return janet_wrap_nil();
} }
static int janet_core_gcsetinterval(JanetArgs args) { static Janet janet_core_gcsetinterval(int32_t argc, Janet *argv) {
int32_t val; janet_arity(argc, 1, 1);
JANET_FIXARITY(args, 1); int32_t val = janet_getinteger(argv, 0);
JANET_ARG_INTEGER(val, args, 0);
if (val < 0) if (val < 0)
JANET_THROW(args, "expected non-negative integer"); janet_panic("expected non-negative integer");
janet_vm_gc_interval = val; janet_vm_gc_interval = val;
JANET_RETURN_NIL(args); return janet_wrap_nil();
} }
static int janet_core_gcinterval(JanetArgs args) { static Janet janet_core_gcinterval(int32_t argc, Janet *argv) {
JANET_FIXARITY(args, 0); (void) argv;
JANET_RETURN_INTEGER(args, janet_vm_gc_interval); janet_arity(argc, 0, 0);
return janet_wrap_number(janet_vm_gc_interval);
} }
static int janet_core_type(JanetArgs args) { static Janet janet_core_type(int32_t argc, Janet *argv) {
JANET_FIXARITY(args, 1); janet_arity(argc, 1, 1);
JanetType t = janet_type(args.v[0]); JanetType t = janet_type(argv[0]);
if (t == JANET_ABSTRACT) { if (t == JANET_ABSTRACT) {
JANET_RETURN(args, janet_ckeywordv(janet_abstract_type(janet_unwrap_abstract(args.v[0]))->name)); return janet_ckeywordv(janet_abstract_type(janet_unwrap_abstract(argv[0]))->name);
} else { } else {
JANET_RETURN(args, janet_ckeywordv(janet_type_names[t])); return janet_ckeywordv(janet_type_names[t]);
} }
} }
static int janet_core_next(JanetArgs args) { static Janet janet_core_next(int32_t argc, Janet *argv) {
Janet ds; janet_arity(argc, 2, 2);
const JanetKV *kv; JanetDictView view = janet_getdictionary(argv, 0);
JANET_FIXARITY(args, 2); const JanetKV *end = view.kvs + view.cap;
JANET_CHECKMANY(args, 0, JANET_TFLAG_DICTIONARY); const JanetKV *kv = janet_checktype(argv[1], JANET_NIL)
ds = args.v[0]; ? view.kvs
if (janet_checktype(ds, JANET_TABLE)) { : janet_dict_find(view.kvs, view.cap, argv[1]) + 1;
JanetTable *t = janet_unwrap_table(ds); while (kv < end) {
kv = janet_checktype(args.v[1], JANET_NIL) if (!janet_checktype(kv->key, JANET_NIL)) return kv->key;
? NULL kv++;
: janet_table_find(t, args.v[1]);
kv = janet_table_next(t, kv);
} else {
const JanetKV *st = janet_unwrap_struct(ds);
kv = janet_checktype(args.v[1], JANET_NIL)
? NULL
: janet_struct_find(st, args.v[1]);
kv = janet_struct_next(st, kv);
} }
if (kv) return janet_wrap_nil();
JANET_RETURN(args, kv->key);
JANET_RETURN_NIL(args);
} }
static int janet_core_hash(JanetArgs args) { static Janet janet_core_hash(int32_t argc, Janet *argv) {
JANET_FIXARITY(args, 1); janet_arity(argc, 1, 1);
JANET_RETURN_INTEGER(args, janet_hash(args.v[0])); return janet_wrap_number(janet_hash(argv[0]));
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
@ -770,28 +758,22 @@ JanetTable *janet_core_env(void) {
janet_gcroot(janet_wrap_table(env)); janet_gcroot(janet_wrap_table(env));
/* Load auxiliary envs */ /* Load auxiliary envs */
{ janet_lib_io(env);
JanetArgs args; janet_lib_math(env);
args.n = 1; janet_lib_array(env);
args.v = &ret; janet_lib_tuple(env);
args.ret = &ret; janet_lib_buffer(env);
janet_lib_io(args); janet_lib_table(env);
janet_lib_math(args); janet_lib_fiber(env);
janet_lib_array(args); janet_lib_os(env);
janet_lib_tuple(args); janet_lib_parse(env);
janet_lib_buffer(args); janet_lib_compile(env);
janet_lib_table(args); janet_lib_debug(env);
janet_lib_fiber(args); janet_lib_string(env);
janet_lib_os(args); janet_lib_marsh(env);
janet_lib_parse(args);
janet_lib_compile(args);
janet_lib_debug(args);
janet_lib_string(args);
janet_lib_marsh(args);
#ifdef JANET_ASSEMBLER #ifdef JANET_ASSEMBLER
janet_lib_asm(args); janet_lib_asm(env);
#endif #endif
}
/* Allow references to the environment */ /* Allow references to the environment */
janet_def(env, "_env", ret, "The environment table for the current scope."); janet_def(env, "_env", ret, "The environment table for the current scope.");

View File

@ -29,26 +29,24 @@
* out of the box. */ * out of the box. */
/* Add a break point to a function */ /* Add a break point to a function */
int janet_debug_break(JanetFuncDef *def, int32_t pc) { void janet_debug_break(JanetFuncDef *def, int32_t pc) {
if (pc >= def->bytecode_length || pc < 0) if (pc >= def->bytecode_length || pc < 0)
return 1; janet_panic("invalid bytecode offset");
def->bytecode[pc] |= 0x80; def->bytecode[pc] |= 0x80;
return 0;
} }
/* Remove a break point from a function */ /* Remove a break point from a function */
int janet_debug_unbreak(JanetFuncDef *def, int32_t pc) { void janet_debug_unbreak(JanetFuncDef *def, int32_t pc) {
if (pc >= def->bytecode_length || pc < 0) if (pc >= def->bytecode_length || pc < 0)
return 1; janet_panic("invalid bytecode offset");
def->bytecode[pc] &= ~((uint32_t)0x80); def->bytecode[pc] &= ~((uint32_t)0x80);
return 0;
} }
/* /*
* Find a location for a breakpoint given a source file an * Find a location for a breakpoint given a source file an
* location. * location.
*/ */
int janet_debug_find( void janet_debug_find(
JanetFuncDef **def_out, int32_t *pc_out, JanetFuncDef **def_out, int32_t *pc_out,
const uint8_t *source, int32_t offset) { const uint8_t *source, int32_t offset) {
/* Scan the heap for right func def */ /* Scan the heap for right func def */
@ -84,9 +82,8 @@ int janet_debug_find(
if (best_def) { if (best_def) {
*def_out = best_def; *def_out = best_def;
*pc_out = besti; *pc_out = besti;
return 0;
} else { } else {
return 1; janet_panic("could not find breakpoint");
} }
} }
@ -96,86 +93,64 @@ int janet_debug_find(
/* Helper to find funcdef and bytecode offset to insert or remove breakpoints. /* Helper to find funcdef and bytecode offset to insert or remove breakpoints.
* Takes a source file name and byte offset. */ * Takes a source file name and byte offset. */
static int helper_find(JanetArgs args, JanetFuncDef **def, int32_t *bytecode_offset) { static void helper_find(int32_t argc, Janet *argv, JanetFuncDef **def, int32_t *bytecode_offset) {
const uint8_t *source; janet_arity(argc, 2, 2);
int32_t source_offset; const uint8_t *source = janet_getstring(argv, 0);
JANET_FIXARITY(args, 2); int32_t source_offset = janet_getinteger(argv, 1);
JANET_ARG_STRING(source, args, 0); janet_debug_find(def, bytecode_offset, source, source_offset);
JANET_ARG_INTEGER(source_offset, args, 1);
if (janet_debug_find(
def, bytecode_offset, source, source_offset)) {
JANET_THROW(args, "could not find breakpoint");
}
JANET_RETURN_NIL(args);
} }
/* Helper to find funcdef and bytecode offset to insert or remove breakpoints. /* Helper to find funcdef and bytecode offset to insert or remove breakpoints.
* Takes a function and byte offset*/ * Takes a function and byte offset*/
static int helper_find_fun(JanetArgs args, JanetFuncDef **def, int32_t *bytecode_offset) { static void helper_find_fun(int32_t argc, Janet *argv, JanetFuncDef **def, int32_t *bytecode_offset) {
JanetFunction *func; janet_arity(argc, 1, 2);
int32_t offset = 0; JanetFunction *func = janet_getfunction(argv, 0);
JANET_MINARITY(args, 1); int32_t offset = (argc == 2) ? janet_getinteger(argv, 1) : 0;
JANET_MAXARITY(args, 2);
JANET_ARG_FUNCTION(func, args, 0);
if (args.n == 2) {
JANET_ARG_INTEGER(offset, args, 1);
}
*def = func->def; *def = func->def;
*bytecode_offset = offset; *bytecode_offset = offset;
JANET_RETURN_NIL(args);
} }
static int cfun_break(JanetArgs args) { static Janet cfun_break(int32_t argc, Janet *argv) {
JanetFuncDef *def; JanetFuncDef *def;
int32_t offset; int32_t offset;
int status = helper_find(args, &def, &offset); helper_find(argc, argv, &def, &offset);
if (status == 0) janet_debug_break(def, offset); janet_debug_break(def, offset);
return status; return janet_wrap_nil();
} }
static int cfun_unbreak(JanetArgs args) { static Janet cfun_unbreak(int32_t argc, Janet *argv) {
JanetFuncDef *def; JanetFuncDef *def;
int32_t offset; int32_t offset;
int status = helper_find(args, &def, &offset); helper_find(argc, argv, &def, &offset);
if (status == 0) janet_debug_unbreak(def, offset); janet_debug_unbreak(def, offset);
return status; return janet_wrap_nil();
} }
static int cfun_fbreak(JanetArgs args) { static Janet cfun_fbreak(int32_t argc, Janet *argv) {
JanetFuncDef *def; JanetFuncDef *def;
int32_t offset; int32_t offset;
int status = helper_find_fun(args, &def, &offset); helper_find_fun(argc, argv, &def, &offset);
if (status == 0) { janet_debug_break(def, offset);
if (janet_debug_break(def, offset)) { return janet_wrap_nil();
JANET_THROW(args, "could not find breakpoint");
}
}
return status;
} }
static int cfun_unfbreak(JanetArgs args) { static Janet cfun_unfbreak(int32_t argc, Janet *argv) {
JanetFuncDef *def; JanetFuncDef *def;
int32_t offset; int32_t offset;
int status = helper_find_fun(args, &def, &offset); helper_find_fun(argc, argv, &def, &offset);
if (status == 0) { janet_debug_unbreak(def, offset);
if (janet_debug_unbreak(def, offset)) { return janet_wrap_nil();
JANET_THROW(args, "could not find breakpoint");
}
}
return status;
} }
static int cfun_lineage(JanetArgs args) { static Janet cfun_lineage(int32_t argc, Janet *argv) {
JanetFiber *fiber; janet_arity(argc, 1, 1);
JanetArray *array; JanetFiber *fiber = janet_getfiber(argv, 0);
JANET_FIXARITY(args, 1); JanetArray *array = janet_array(0);
JANET_ARG_FIBER(fiber, args, 0);
array = janet_array(0);
while (fiber) { while (fiber) {
janet_array_push(array, janet_wrap_fiber(fiber)); janet_array_push(array, janet_wrap_fiber(fiber));
fiber = fiber->child; fiber = fiber->child;
} }
JANET_RETURN_ARRAY(args, array); return janet_wrap_array(array);
} }
/* Extract info from one stack frame */ /* Extract info from one stack frame */
@ -224,12 +199,10 @@ static Janet doframe(JanetStackFrame *frame) {
return janet_wrap_table(t); return janet_wrap_table(t);
} }
static int cfun_stack(JanetArgs args) { static Janet cfun_stack(int32_t argc, Janet *argv) {
JanetFiber *fiber; janet_arity(argc, 1, 1);
JanetArray *array; JanetFiber *fiber = janet_getfiber(argv, 0);
JANET_FIXARITY(args, 1); JanetArray *array = janet_array(0);
JANET_ARG_FIBER(fiber, args, 0);
array = janet_array(0);
{ {
int32_t i = fiber->frame; int32_t i = fiber->frame;
JanetStackFrame *frame; JanetStackFrame *frame;
@ -239,18 +212,16 @@ static int cfun_stack(JanetArgs args) {
i = frame->prevframe; i = frame->prevframe;
} }
} }
JANET_RETURN_ARRAY(args, array); return janet_wrap_array(array);
} }
static int cfun_argstack(JanetArgs args) { static Janet cfun_argstack(int32_t argc, Janet *argv) {
JanetFiber *fiber; janet_arity(argc, 1, 1);
JanetArray *array; JanetFiber *fiber = janet_getfiber(argv, 0);
JANET_FIXARITY(args, 1); JanetArray *array = janet_array(fiber->stacktop - fiber->stackstart);
JANET_ARG_FIBER(fiber, args, 0);
array = janet_array(fiber->stacktop - fiber->stackstart);
memcpy(array->data, fiber->data + fiber->stackstart, array->capacity * sizeof(Janet)); memcpy(array->data, fiber->data + fiber->stackstart, array->capacity * sizeof(Janet));
array->count = array->capacity; array->count = array->capacity;
JANET_RETURN_ARRAY(args, array); return janet_wrap_array(array);
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
@ -306,8 +277,6 @@ static const JanetReg cfuns[] = {
}; };
/* Module entry point */ /* Module entry point */
int janet_lib_debug(JanetArgs args) { void janet_lib_debug(JanetTable *env) {
JanetTable *env = janet_env(args);
janet_cfuns(env, NULL, cfuns); janet_cfuns(env, NULL, cfuns);
return 0;
} }

View File

@ -292,31 +292,29 @@ void janet_fiber_popframe(JanetFiber *fiber) {
/* CFuns */ /* CFuns */
static int cfun_new(JanetArgs args) { static Janet cfun_new(int32_t argc, Janet *argv) {
janet_arity(argc, 1, 2);
JanetFunction *func = janet_getfunction(argv, 0);
JanetFiber *fiber; JanetFiber *fiber;
JanetFunction *func;
JANET_MINARITY(args, 1);
JANET_MAXARITY(args, 2);
JANET_ARG_FUNCTION(func, args, 0);
if (func->def->flags & JANET_FUNCDEF_FLAG_FIXARITY) { if (func->def->flags & JANET_FUNCDEF_FLAG_FIXARITY) {
if (func->def->arity != 0) { if (func->def->arity != 0) {
JANET_THROW(args, "expected nullary function in fiber constructor"); janet_panic("expected nullary function in fiber constructor");
} }
} }
fiber = janet_fiber(func, 64); fiber = janet_fiber(func, 64);
if (args.n == 2) { if (argc == 2) {
const uint8_t *flags; int32_t i;
int32_t len, i; JanetByteView view = janet_getbytes(argv, 1);
JANET_ARG_BYTES(flags, len, args, 1);
fiber->flags = 0; fiber->flags = 0;
janet_fiber_set_status(fiber, JANET_STATUS_NEW); janet_fiber_set_status(fiber, JANET_STATUS_NEW);
for (i = 0; i < len; i++) { for (i = 0; i < view.len; i++) {
if (flags[i] >= '0' && flags[i] <= '9') { if (view.bytes[i] >= '0' && view.bytes[i] <= '9') {
fiber->flags |= JANET_FIBER_MASK_USERN(flags[i] - '0'); fiber->flags |= JANET_FIBER_MASK_USERN(view.bytes[i] - '0');
} else { } else {
switch (flags[i]) { switch (view.bytes[i]) {
default: default:
JANET_THROW(args, "invalid flag, expected a, d, e, u, or y"); janet_panicf("invalid flag %c, expected a, d, e, u, or y", view.bytes[i]);
break;
case 'a': case 'a':
fiber->flags |= fiber->flags |=
JANET_FIBER_MASK_DEBUG | JANET_FIBER_MASK_DEBUG |
@ -340,41 +338,38 @@ static int cfun_new(JanetArgs args) {
} }
} }
} }
JANET_RETURN_FIBER(args, fiber); return janet_wrap_fiber(fiber);
} }
static int cfun_status(JanetArgs args) { static Janet cfun_status(int32_t argc, Janet *argv) {
JanetFiber *fiber; janet_arity(argc, 1, 1);
JANET_FIXARITY(args, 1); JanetFiber *fiber = janet_getfiber(argv, 0);
JANET_ARG_FIBER(fiber, args, 0);
uint32_t s = (fiber->flags & JANET_FIBER_STATUS_MASK) >> uint32_t s = (fiber->flags & JANET_FIBER_STATUS_MASK) >>
JANET_FIBER_STATUS_OFFSET; JANET_FIBER_STATUS_OFFSET;
JANET_RETURN_CKEYWORD(args, janet_status_names[s]); return janet_ckeywordv(janet_status_names[s]);
} }
static int cfun_current(JanetArgs args) { static Janet cfun_current(int32_t argc, Janet *argv) {
JANET_FIXARITY(args, 0); (void) argv;
JANET_RETURN_FIBER(args, janet_vm_fiber); janet_arity(argc, 0, 0);
return janet_wrap_fiber(janet_vm_fiber);
} }
static int cfun_maxstack(JanetArgs args) { static Janet cfun_maxstack(int32_t argc, Janet *argv) {
JanetFiber *fiber; janet_arity(argc, 1, 1);
JANET_FIXARITY(args, 1); JanetFiber *fiber = janet_getfiber(argv, 0);
JANET_ARG_FIBER(fiber, args, 0); return janet_wrap_integer(fiber->maxstack);
JANET_RETURN_INTEGER(args, fiber->maxstack);
} }
static int cfun_setmaxstack(JanetArgs args) { static Janet cfun_setmaxstack(int32_t argc, Janet *argv) {
JanetFiber *fiber; janet_arity(argc, 2, 2);
int32_t maxs; JanetFiber *fiber = janet_getfiber(argv, 0);
JANET_FIXARITY(args, 2); int32_t maxs = janet_getinteger(argv, 1);
JANET_ARG_FIBER(fiber, args, 0);
JANET_ARG_INTEGER(maxs, args, 1);
if (maxs < 0) { if (maxs < 0) {
JANET_THROW(args, "expected positive integer"); janet_panic("expected positive integer");
} }
fiber->maxstack = maxs; fiber->maxstack = maxs;
JANET_RETURN_FIBER(args, fiber); return argv[0];
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
@ -425,8 +420,6 @@ static const JanetReg cfuns[] = {
}; };
/* Module entry point */ /* Module entry point */
int janet_lib_fiber(JanetArgs args) { void janet_lib_fiber(JanetTable *env) {
JanetTable *env = janet_env(args);
janet_cfuns(env, NULL, cfuns); janet_cfuns(env, NULL, cfuns);
return 0;
} }

View File

@ -53,13 +53,16 @@ JanetAbstractType janet_io_filetype = {
}; };
/* Check argupments to fopen */ /* Check argupments to fopen */
static int checkflags(const uint8_t *str, int32_t len) { static int checkflags(const uint8_t *str) {
int flags = 0; int flags = 0;
int32_t i; int32_t i;
if (!len || len > 3) return -1; int32_t len = janet_string_length(str);
if (!len || len > 3)
janet_panic("file mode must have a length between 1 and 3");
switch (*str) { switch (*str) {
default: default:
return -1; janet_panicf("invalid flag %c, expected w, a, or r", *str);
break;
case 'w': case 'w':
flags |= IO_WRITE; flags |= IO_WRITE;
break; break;
@ -73,7 +76,8 @@ static int checkflags(const uint8_t *str, int32_t len) {
for (i = 1; i < len; i++) { for (i = 1; i < len; i++) {
switch (str[i]) { switch (str[i]) {
default: default:
return -1; janet_panicf("invalid flag %c, expected + or b", str[i]);
break;
case '+': case '+':
if (flags & IO_UPDATE) return -1; if (flags & IO_UPDATE) return -1;
flags |= IO_UPDATE; flags |= IO_UPDATE;
@ -87,41 +91,6 @@ static int checkflags(const uint8_t *str, int32_t len) {
return flags; return flags;
} }
/* Check file argument */
static IOFile *checkfile(JanetArgs args, int32_t n) {
IOFile *iof;
if (n >= args.n) {
*args.ret = janet_cstringv("expected core.file");
return NULL;
}
if (!janet_checktype(args.v[n], JANET_ABSTRACT)) {
*args.ret = janet_cstringv("expected core.file");
return NULL;
}
iof = (IOFile *) janet_unwrap_abstract(args.v[n]);
if (janet_abstract_type(iof) != &janet_io_filetype) {
*args.ret = janet_cstringv("expected core.file");
return NULL;
}
return iof;
}
/* Check buffer argument */
static JanetBuffer *checkbuffer(JanetArgs args, int32_t n, int optional) {
if (optional && n == args.n) {
return janet_buffer(0);
}
if (n >= args.n) {
*args.ret = janet_cstringv("expected buffer");
return NULL;
}
if (!janet_checktype(args.v[n], JANET_BUFFER)) {
*args.ret = janet_cstringv("expected buffer");
return NULL;
}
return janet_unwrap_abstract(args.v[n]);
}
static Janet makef(FILE *f, int flags) { static Janet makef(FILE *f, int flags) {
IOFile *iof = (IOFile *) janet_abstract(&janet_io_filetype, sizeof(IOFile)); IOFile *iof = (IOFile *) janet_abstract(&janet_io_filetype, sizeof(IOFile));
iof->file = f; iof->file = f;
@ -130,97 +99,75 @@ static Janet makef(FILE *f, int flags) {
} }
/* Open a process */ /* Open a process */
static int janet_io_popen(JanetArgs args) { static Janet janet_io_popen(int32_t argc, Janet *argv) {
const uint8_t *fname, *fmode; janet_arity(argc, 1, 2);
int32_t modelen; const uint8_t *fname = janet_getstring(argv, 0);
FILE *f; const uint8_t *fmode = NULL;
int flags; if (argc == 2) {
JANET_MINARITY(args, 1); fmode = janet_getkeyword(argv, 1);
JANET_MAXARITY(args, 2); if (janet_string_length(fmode) != 1 ||
JANET_ARG_STRING(fname, args, 0); !(fmode[0] == 'r' || fmode[0] == 'w')) {
if (args.n == 2) { janet_panicf("invalid file mode :%S, expected :r or :w", fmode);
if (!janet_checktype(args.v[1], JANET_STRING) && }
!janet_checktype(args.v[1], JANET_SYMBOL))
JANET_THROW(args, "expected string mode");
fmode = janet_unwrap_string(args.v[1]);
modelen = janet_string_length(fmode);
} else {
fmode = (const uint8_t *)"r";
modelen = 1;
} }
if (modelen != 1 || !(fmode[0] == 'r' || fmode[0] == 'w')) { int flags = (fmode && fmode[0] == '2')
JANET_THROW(args, "invalid file mode"); ? IO_PIPED | IO_WRITE
} : IO_PIPED | IO_READ;
flags = (fmode[0] == 'r') ? IO_PIPED | IO_READ : IO_PIPED | IO_WRITE;
#ifdef JANET_WINDOWS #ifdef JANET_WINDOWS
#define popen _popen #define popen _popen
#endif #endif
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
#define popen(A, B) (errno = 0, NULL) #define popen(A, B) (errno = 0, NULL)
#endif #endif
f = popen((const char *)fname, (const char *)fmode); FILE *f = popen((const char *)fname, (const char *)fmode);
if (!f) { if (!f) {
if (errno == EMFILE) { return janet_wrap_nil();
JANET_THROW(args, "too many streams are open");
}
JANET_THROW(args, "could not open file");
} }
JANET_RETURN(args, makef(f, flags)); return makef(f, flags);
} }
/* Open a a file and return a userdata wrapper around the C file API. */ /* Open a a file and return a userdata wrapper around the C file API. */
static int janet_io_fopen(JanetArgs args) { static Janet janet_io_fopen(int32_t argc, Janet *argv) {
const uint8_t *fname, *fmode; janet_arity(argc, 1, 2);
int32_t modelen; const uint8_t *fname = janet_getstring(argv, 0);
FILE *f; const uint8_t *fmode;
int flags; int flags;
JANET_MINARITY(args, 1); if (argc == 2) {
JANET_MAXARITY(args, 2); fmode = janet_getkeyword(argv, 1);
JANET_ARG_STRING(fname, args, 0); flags = checkflags(fmode);
if (args.n == 2) {
if (!janet_checktype(args.v[1], JANET_STRING) &&
!janet_checktype(args.v[1], JANET_SYMBOL))
JANET_THROW(args, "expected string mode");
fmode = janet_unwrap_string(args.v[1]);
modelen = janet_string_length(fmode);
} else { } else {
fmode = (const uint8_t *)"r"; fmode = (const uint8_t *)"r";
modelen = 1; flags = IO_READ;
} }
if ((flags = checkflags(fmode, modelen)) < 0) { FILE *f = fopen((const char *)fname, (const char *)fmode);
JANET_THROW(args, "invalid file mode"); return f ? makef(f, flags) : janet_wrap_nil();
}
f = fopen((const char *)fname, (const char *)fmode);
JANET_RETURN(args, f ? makef(f, flags) : janet_wrap_nil());
} }
/* Read up to n bytes into buffer. Return error string if error. */ /* Read up to n bytes into buffer. Return error string if error. */
static const char *read_chunk(IOFile *iof, JanetBuffer *buffer, int32_t nBytesMax) { static void read_chunk(IOFile *iof, JanetBuffer *buffer, int32_t nBytesMax) {
if (!(iof->flags & (IO_READ | IO_UPDATE))) if (!(iof->flags & (IO_READ | IO_UPDATE)))
return "file is not readable"; janet_panic("file is not readable");
/* Ensure buffer size */ janet_buffer_extra(buffer, nBytesMax);
if (janet_buffer_extra(buffer, nBytesMax))
return "buffer overflow";
size_t ntoread = nBytesMax; size_t ntoread = nBytesMax;
size_t nread = fread((char *)(buffer->data + buffer->count), 1, ntoread, iof->file); size_t nread = fread((char *)(buffer->data + buffer->count), 1, ntoread, iof->file);
if (nread != ntoread && ferror(iof->file)) if (nread != ntoread && ferror(iof->file))
return "could not read file"; janet_panic("could not read file");
buffer->count += (int32_t) nread; buffer->count += (int32_t) nread;
return NULL;
} }
/* Read a certain number of bytes into memory */ /* Read a certain number of bytes into memory */
static int janet_io_fread(JanetArgs args) { static Janet janet_io_fread(int32_t argc, Janet *argv) {
JanetBuffer *b; janet_arity(argc, 2, 3);
IOFile *iof = checkfile(args, 0); IOFile *iof = janet_getabstract(argv, 0, &janet_io_filetype);
if (!iof) return 1; if (iof->flags & IO_CLOSED) janet_panic("file is closed");
if (iof->flags & IO_CLOSED) JanetBuffer *buffer;
JANET_THROW(args, "file is closed"); if (argc == 2) {
b = checkbuffer(args, 2, 1); buffer = janet_buffer(0);
if (!b) return 1; } else {
JANET_MINARITY(args, 2); buffer = janet_getbuffer(argv, 2);
if (janet_checktype(args.v[1], JANET_KEYWORD)) { }
const uint8_t *sym = janet_unwrap_symbol(args.v[1]); if (janet_checktype(argv[1], JANET_KEYWORD)) {
const uint8_t *sym = janet_unwrap_keyword(argv[1]);
if (!janet_cstrcmp(sym, "all")) { if (!janet_cstrcmp(sym, "all")) {
/* Read whole file */ /* Read whole file */
int status = fseek(iof->file, 0, SEEK_SET); int status = fseek(iof->file, 0, SEEK_SET);
@ -228,71 +175,66 @@ static int janet_io_fread(JanetArgs args) {
/* backwards fseek did not work (stream like popen) */ /* backwards fseek did not work (stream like popen) */
int32_t sizeBefore; int32_t sizeBefore;
do { do {
sizeBefore = b->count; sizeBefore = buffer->count;
const char *maybeErr = read_chunk(iof, b, 1024); read_chunk(iof, buffer, 1024);
if (maybeErr) JANET_THROW(args, maybeErr); } while (sizeBefore < buffer->count);
} while (sizeBefore < b->count);
} else { } else {
fseek(iof->file, 0, SEEK_END); fseek(iof->file, 0, SEEK_END);
long fsize = ftell(iof->file); long fsize = ftell(iof->file);
fseek(iof->file, 0, SEEK_SET); fseek(iof->file, 0, SEEK_SET);
if (fsize > INT32_MAX) JANET_THROW(args, "buffer overflow"); read_chunk(iof, buffer, (int32_t) fsize);
const char *maybeErr = read_chunk(iof, b, (int32_t) fsize);;
if (maybeErr) JANET_THROW(args, maybeErr);
} }
} else if (!janet_cstrcmp(sym, "line")) { } else if (!janet_cstrcmp(sym, "line")) {
for (;;) { for (;;) {
int x = fgetc(iof->file); int x = fgetc(iof->file);
if (x != EOF && janet_buffer_push_u8(b, (uint8_t)x)) if (x != EOF) janet_buffer_push_u8(buffer, (uint8_t)x);
JANET_THROW(args, "buffer overflow");
if (x == EOF || x == '\n') break; if (x == EOF || x == '\n') break;
} }
} else { } else {
JANET_THROW(args, "expected one of :all, :line"); janet_panicf("expected one of :all, :line, got %v", argv[1]);
} }
} else if (!janet_checkint(args.v[1])) {
JANET_THROW(args, "expected positive integer");
} else { } else {
int32_t len = janet_unwrap_integer(args.v[1]); int32_t len = janet_getinteger(argv, 1);
if (len < 0) JANET_THROW(args, "expected positive integer"); if (len < 0) janet_panic("expected positive integer");
const char *maybeErr = read_chunk(iof, b, len); read_chunk(iof, buffer, len);
if (maybeErr) JANET_THROW(args, maybeErr);
} }
JANET_RETURN(args, janet_wrap_buffer(b)); return janet_wrap_buffer(buffer);
} }
/* Write bytes to a file */ /* Write bytes to a file */
static int janet_io_fwrite(JanetArgs args) { static Janet janet_io_fwrite(int32_t argc, Janet *argv) {
int32_t len, i; janet_arity(argc, 1, -1);
const uint8_t *str; IOFile *iof = janet_getabstract(argv, 0, &janet_io_filetype);
IOFile *iof = checkfile(args, 0);
if (!iof) return 1;
if (iof->flags & IO_CLOSED) if (iof->flags & IO_CLOSED)
JANET_THROW(args, "file is closed"); janet_panic("file is closed");
if (!(iof->flags & (IO_WRITE | IO_APPEND | IO_UPDATE))) if (!(iof->flags & (IO_WRITE | IO_APPEND | IO_UPDATE)))
JANET_THROW(args, "file is not writeable"); janet_panic("file is not writeable");
for (i = 1; i < args.n; i++) { int32_t i;
JANET_CHECKMANY(args, i, JANET_TFLAG_BYTES); /* Verify all arguments before writing to file */
} for (i = 1; i < argc; i++)
for (i = 1; i < args.n; i++) { janet_getbytes(argv, i);
JANET_ARG_BYTES(str, len, args, i); for (i = 1; i < argc; i++) {
if (len) { JanetByteView view = janet_getbytes(argv, i);
if (!fwrite(str, len, 1, iof->file)) JANET_THROW(args, "error writing to file"); if (view.len) {
if (!fwrite(view.bytes, view.len, 1, iof->file)) {
janet_panic("error writing to file");
}
} }
} }
JANET_RETURN(args, janet_wrap_abstract(iof)); return argv[0];
} }
/* Flush the bytes in the file */ /* Flush the bytes in the file */
static int janet_io_fflush(JanetArgs args) { static Janet janet_io_fflush(int32_t argc, Janet *argv) {
IOFile *iof = checkfile(args, 0); janet_arity(argc, 1, 1);
if (!iof) return 1; IOFile *iof = janet_getabstract(argv, 0, &janet_io_filetype);
if (iof->flags & IO_CLOSED) if (iof->flags & IO_CLOSED)
JANET_THROW(args, "file is closed"); janet_panic("file is closed");
if (!(iof->flags & (IO_WRITE | IO_APPEND | IO_UPDATE))) if (!(iof->flags & (IO_WRITE | IO_APPEND | IO_UPDATE)))
JANET_THROW(args, "file is not flushable"); janet_panic("file is not writeable");
if (fflush(iof->file)) JANET_THROW(args, "could not flush file"); if (fflush(iof->file))
JANET_RETURN(args, janet_wrap_abstract(iof)); janet_panic("could not flush file");
return argv[0];
} }
/* Cleanup a file */ /* Cleanup a file */
@ -306,38 +248,35 @@ static int janet_io_gc(void *p, size_t len) {
} }
/* Close a file */ /* Close a file */
static int janet_io_fclose(JanetArgs args) { static Janet janet_io_fclose(int32_t argc, Janet *argv) {
IOFile *iof = checkfile(args, 0); janet_arity(argc, 1, 1);
if (!iof) return 1; IOFile *iof = janet_getabstract(argv, 0, &janet_io_filetype);
if (iof->flags & (IO_CLOSED)) if (iof->flags & IO_CLOSED)
JANET_THROW(args, "file already closed"); janet_panic("file is closed");
if (iof->flags & (IO_NOT_CLOSEABLE)) if (iof->flags & (IO_NOT_CLOSEABLE))
JANET_THROW(args, "file not closable"); janet_panic("file not closable");
if (iof->flags & IO_PIPED) { if (iof->flags & IO_PIPED) {
#ifdef JANET_WINDOWS #ifdef JANET_WINDOWS
#define pclose _pclose #define pclose _pclose
#endif #endif
if (pclose(iof->file)) JANET_THROW(args, "could not close file"); if (pclose(iof->file)) janet_panic("could not close file");
} else { } else {
if (fclose(iof->file)) JANET_THROW(args, "could not close file"); if (fclose(iof->file)) janet_panic("could not close file");
} }
iof->flags |= IO_CLOSED; iof->flags |= IO_CLOSED;
JANET_RETURN(args, janet_wrap_abstract(iof)); return argv[0];
} }
/* Seek a file */ /* Seek a file */
static int janet_io_fseek(JanetArgs args) { static Janet janet_io_fseek(int32_t argc, Janet *argv) {
janet_arity(argc, 2, 3);
IOFile *iof = janet_getabstract(argv, 0, &janet_io_filetype);
if (iof->flags & IO_CLOSED)
janet_panic("file is closed");
long int offset = 0; long int offset = 0;
int whence = SEEK_CUR; int whence = SEEK_CUR;
IOFile *iof = checkfile(args, 0); if (argc >= 2) {
if (!iof) return 1; const uint8_t *whence_sym = janet_getkeyword(argv, 1);
if (iof->flags & IO_CLOSED)
JANET_THROW(args, "file is closed");
if (args.n >= 2) {
const uint8_t *whence_sym;
if (!janet_checktype(args.v[1], JANET_KEYWORD))
JANET_THROW(args, "expected keyword");
whence_sym = janet_unwrap_symbol(args.v[1]);
if (!janet_cstrcmp(whence_sym, "cur")) { if (!janet_cstrcmp(whence_sym, "cur")) {
whence = SEEK_CUR; whence = SEEK_CUR;
} else if (!janet_cstrcmp(whence_sym, "set")) { } else if (!janet_cstrcmp(whence_sym, "set")) {
@ -345,17 +284,14 @@ static int janet_io_fseek(JanetArgs args) {
} else if (!janet_cstrcmp(whence_sym, "end")) { } else if (!janet_cstrcmp(whence_sym, "end")) {
whence = SEEK_END; whence = SEEK_END;
} else { } else {
JANET_THROW(args, "expected one of :cur, :set, :end"); janet_panicf("expected one of :cur, :set, :end, got %v", argv[1]);
} }
if (args.n >= 3) { if (argc == 3) {
double doffset; offset = janet_getinteger64(argv, 2);
JANET_ARG_NUMBER(doffset, args, 2);
offset = (long int)doffset;
} }
} }
if (fseek(iof->file, offset, whence)) if (fseek(iof->file, offset, whence)) janet_panic("error seeking file");
JANET_THROW(args, "error seeking file"); return argv[0];
JANET_RETURN(args, args.v[0]);
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
@ -420,25 +356,18 @@ static const JanetReg cfuns[] = {
}; };
/* Module entry point */ /* Module entry point */
int janet_lib_io(JanetArgs args) { void janet_lib_io(JanetTable *env) {
JanetTable *env = janet_env(args);
janet_cfuns(env, NULL, cfuns); janet_cfuns(env, NULL, cfuns);
/* stdout */ /* stdout */
janet_def(env, "stdout", janet_def(env, "stdout",
makef(stdout, IO_APPEND | IO_NOT_CLOSEABLE | IO_SERIALIZABLE), makef(stdout, IO_APPEND | IO_NOT_CLOSEABLE | IO_SERIALIZABLE),
"The standard output file."); "The standard output file.");
/* stderr */ /* stderr */
janet_def(env, "stderr", janet_def(env, "stderr",
makef(stderr, IO_APPEND | IO_NOT_CLOSEABLE | IO_SERIALIZABLE), makef(stderr, IO_APPEND | IO_NOT_CLOSEABLE | IO_SERIALIZABLE),
"The standard error file."); "The standard error file.");
/* stdin */ /* stdin */
janet_def(env, "stdin", janet_def(env, "stdin",
makef(stdin, IO_READ | IO_NOT_CLOSEABLE | IO_SERIALIZABLE), makef(stdin, IO_READ | IO_NOT_CLOSEABLE | IO_SERIALIZABLE),
"The standard input file."); "The standard input file.");
return 0;
} }

View File

@ -21,7 +21,6 @@
*/ */
#include <janet/janet.h> #include <janet/janet.h>
#include <setjmp.h>
#include "state.h" #include "state.h"
#include "vector.h" #include "vector.h"
@ -124,7 +123,7 @@ JanetTable *janet_env_lookup(JanetTable *env) {
/* Marshal an integer onto the buffer */ /* Marshal an integer onto the buffer */
static void pushint(MarshalState *st, int32_t x) { static void pushint(MarshalState *st, int32_t x) {
if (x >= 0 && x < 200) { if (x >= 0 && x < 200) {
if (janet_buffer_push_u8(st->buf, x)) longjmp(st->err, MR_OVERFLOW); janet_buffer_push_u8(st->buf, x);
} else { } else {
uint8_t intbuf[5]; uint8_t intbuf[5];
intbuf[0] = LB_INTEGER; intbuf[0] = LB_INTEGER;
@ -132,16 +131,16 @@ static void pushint(MarshalState *st, int32_t x) {
intbuf[2] = (x >> 8) & 0xFF; intbuf[2] = (x >> 8) & 0xFF;
intbuf[3] = (x >> 16) & 0xFF; intbuf[3] = (x >> 16) & 0xFF;
intbuf[4] = (x >> 24) & 0xFF; intbuf[4] = (x >> 24) & 0xFF;
if (janet_buffer_push_bytes(st->buf, intbuf, 5)) longjmp(st->err, MR_OVERFLOW); janet_buffer_push_bytes(st->buf, intbuf, 5);
} }
} }
static void pushbyte(MarshalState *st, uint8_t b) { static void pushbyte(MarshalState *st, uint8_t b) {
if (janet_buffer_push_u8(st->buf, b)) longjmp(st->err, MR_OVERFLOW); janet_buffer_push_u8(st->buf, b);
} }
static void pushbytes(MarshalState *st, const uint8_t *bytes, int32_t len) { static void pushbytes(MarshalState *st, const uint8_t *bytes, int32_t len) {
if (janet_buffer_push_bytes(st->buf, bytes, len)) longjmp(st->err, MR_OVERFLOW); janet_buffer_push_bytes(st->buf, bytes, len);
} }
/* Forward declaration to enable mutual recursion. */ /* Forward declaration to enable mutual recursion. */
@ -1102,61 +1101,46 @@ int janet_unmarshal(
/* C functions */ /* C functions */
static int cfun_env_lookup(JanetArgs args) { static Janet cfun_env_lookup(int32_t argc, Janet *argv) {
JanetTable *env; janet_arity(argc, 1, 1);
JANET_FIXARITY(args, 1); JanetTable *env = janet_gettable(argv, 0);
JANET_ARG_TABLE(env, args, 0); return janet_wrap_table(janet_env_lookup(env));
JANET_RETURN_TABLE(args, janet_env_lookup(env));
} }
static int cfun_marshal(JanetArgs args) { static Janet cfun_marshal(int32_t argc, Janet *argv) {
janet_arity(argc, 1, 2);
JanetBuffer *buffer; JanetBuffer *buffer;
JanetTable *rreg; JanetTable *rreg = NULL;
Janet err_param = janet_wrap_nil(); Janet err_param = janet_wrap_nil();
int status; int status;
JANET_MINARITY(args, 1); if (argc > 1) {
JANET_MAXARITY(args, 3); rreg = janet_gettable(argv, 1);
if (args.n > 1) {
/* Reverse Registry provided */
JANET_ARG_TABLE(rreg, args, 1);
} else {
rreg = NULL;
} }
if (args.n > 2) { if (argc > 2) {
/* Buffer provided */ buffer = janet_getbuffer(argv, 2);
JANET_ARG_BUFFER(buffer, args, 2);
} else { } else {
buffer = janet_buffer(10); buffer = janet_buffer(10);
} }
status = janet_marshal(buffer, args.v[0], &err_param, rreg, 0); status = janet_marshal(buffer, argv[0], &err_param, rreg, 0);
if (status) { if (status)
const uint8_t *errstr = janet_formatc( janet_panicf("%s for %V", mr_strings[status], err_param);
"%s for %V", return janet_wrap_buffer(buffer);
mr_strings[status],
err_param);
JANET_THROWV(args, janet_wrap_string(errstr));
}
JANET_RETURN_BUFFER(args, buffer);
} }
static int cfun_unmarshal(JanetArgs args) { static Janet cfun_unmarshal(int32_t argc, Janet *argv) {
const uint8_t *bytes; janet_arity(argc, 1, 2);
JanetTable *reg; JanetByteView view = janet_getbytes(argv, 0);
int32_t len; JanetTable *reg = NULL;
Janet ret;
int status; int status;
JANET_MINARITY(args, 1); if (argc > 1) {
JANET_MAXARITY(args, 2); reg = janet_gettable(argv, 1);
JANET_ARG_BYTES(bytes, len, args, 0);
if (args.n > 1) {
JANET_ARG_TABLE(reg, args, 1);
} else {
reg = NULL;
} }
status = janet_unmarshal(bytes, (size_t) len, 0, args.ret, reg, NULL); status = janet_unmarshal(view.bytes, (size_t) view.len, 0, &ret, reg, NULL);
if (status) { if (status) {
JANET_THROW(args, umr_strings[status]); janet_panic(umr_strings[status]);
} }
return JANET_SIGNAL_OK; return ret;
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
@ -1185,8 +1169,6 @@ static const JanetReg cfuns[] = {
}; };
/* Module entry point */ /* Module entry point */
int janet_lib_marsh(JanetArgs args) { void janet_lib_marsh(JanetTable *env) {
JanetTable *env = janet_env(args);
janet_cfuns(env, NULL, cfuns); janet_cfuns(env, NULL, cfuns);
return 0;
} }

View File

@ -24,35 +24,33 @@
#include <math.h> #include <math.h>
/* Get a random number */ /* Get a random number */
int janet_rand(JanetArgs args) { Janet janet_rand(int32_t argc, Janet *argv) {
JANET_FIXARITY(args, 0); (void) argv;
janet_arity(argc, 0, 0);
double r = (rand() % RAND_MAX) / ((double) RAND_MAX); double r = (rand() % RAND_MAX) / ((double) RAND_MAX);
JANET_RETURN_NUMBER(args, r); return janet_wrap_number(r);
} }
/* Seed the random number generator */ /* Seed the random number generator */
int janet_srand(JanetArgs args) { Janet janet_srand(int32_t argc, Janet *argv) {
int32_t x = 0; janet_arity(argc, 1, 1);
JANET_FIXARITY(args, 1); int32_t x = janet_getinteger(argv, 0);
JANET_ARG_INTEGER(x, args, 0);
srand((unsigned) x); srand((unsigned) x);
return 0; return janet_wrap_nil();
} }
int janet_remainder(JanetArgs args) { Janet janet_remainder(int32_t argc, Janet *argv) {
JANET_FIXARITY(args, 2); janet_arity(argc, 2, 2);
double x, y; double x = janet_getnumber(argv, 0);
JANET_ARG_NUMBER(x, args, 0); double y = janet_getnumber(argv, 1);
JANET_ARG_NUMBER(y, args, 1); return janet_wrap_number(fmod(x, y));
JANET_RETURN_NUMBER(args, fmod(x, y));
} }
#define JANET_DEFINE_MATHOP(name, fop)\ #define JANET_DEFINE_MATHOP(name, fop)\
int janet_##name(JanetArgs args) {\ Janet janet_##name(int32_t argc, Janet *argv) {\
double x;\ janet_arity(argc, 1, 1); \
JANET_FIXARITY(args, 1);\ double x = janet_getnumber(argv, 0); \
JANET_ARG_NUMBER(x, args, 0);\ return janet_wrap_number(fop(x)); \
JANET_RETURN_NUMBER(args, fop(x));\
} }
JANET_DEFINE_MATHOP(acos, acos) JANET_DEFINE_MATHOP(acos, acos)
@ -73,20 +71,19 @@ JANET_DEFINE_MATHOP(fabs, fabs)
JANET_DEFINE_MATHOP(floor, floor) JANET_DEFINE_MATHOP(floor, floor)
#define JANET_DEFINE_MATH2OP(name, fop)\ #define JANET_DEFINE_MATH2OP(name, fop)\
int janet_##name(JanetArgs args) {\ Janet janet_##name(int32_t argc, Janet *argv) {\
double lhs, rhs;\ janet_arity(argc, 2, 2); \
JANET_FIXARITY(args, 2);\ double lhs = janet_getnumber(argv, 0); \
JANET_ARG_NUMBER(lhs, args, 0);\ double rhs = janet_getnumber(argv, 1); \
JANET_ARG_NUMBER(rhs, args, 1);\ return janet_wrap_number(fop(lhs, rhs)); \
JANET_RETURN_NUMBER(args, fop(lhs, rhs));\
}\ }\
JANET_DEFINE_MATH2OP(atan2, atan2) JANET_DEFINE_MATH2OP(atan2, atan2)
JANET_DEFINE_MATH2OP(pow, pow) JANET_DEFINE_MATH2OP(pow, pow)
static int janet_not(JanetArgs args) { static Janet janet_not(int32_t argc, Janet *argv) {
JANET_FIXARITY(args, 1); janet_arity(argc, 1, 1);
JANET_RETURN_BOOLEAN(args, !janet_truthy(args.v[0])); return janet_wrap_boolean(!janet_truthy(argv[0]));
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
@ -162,15 +159,12 @@ static const JanetReg cfuns[] = {
}; };
/* Module entry point */ /* Module entry point */
int janet_lib_math(JanetArgs args) { void janet_lib_math(JanetTable *env) {
JanetTable *env = janet_env(args);
janet_cfuns(env, NULL, cfuns); janet_cfuns(env, NULL, cfuns);
janet_def(env, "math/pi", janet_wrap_number(3.1415926535897931), janet_def(env, "math/pi", janet_wrap_number(3.1415926535897931),
"The value pi."); "The value pi.");
janet_def(env, "math/e", janet_wrap_number(2.7182818284590451), janet_def(env, "math/e", janet_wrap_number(2.7182818284590451),
"The base of the natural log."); "The base of the natural log.");
janet_def(env, "math/inf", janet_wrap_number(INFINITY), janet_def(env, "math/inf", janet_wrap_number(INFINITY),
"The number representing positive infinity"); "The number representing positive infinity");
return 0;
} }

View File

@ -40,27 +40,28 @@
#include <mach/mach.h> #include <mach/mach.h>
#endif #endif
static int os_which(JanetArgs args) { static Janet os_which(int32_t argc, Janet *argv) {
janet_arity(argc, 0, 0);
(void) argv;
#ifdef JANET_WINDOWS #ifdef JANET_WINDOWS
JANET_RETURN_CKEYWORD(args, "windows"); return janet_ckeywordv("windows");
#elif __APPLE__ #elif __APPLE__
JANET_RETURN_CKEYWORD(args, "macos"); return janet_ckeywordv("macos");
#elif defined(__EMSCRIPTEN__) #elif defined(__EMSCRIPTEN__)
JANET_RETURN_CKEYWORD(args, "web"); return janet_ckeywordv("web");
#else #else
JANET_RETURN_CKEYWORD(args, "posix"); return janet_ckeywordv("posix");
#endif #endif
} }
#ifdef JANET_WINDOWS #ifdef JANET_WINDOWS
static int os_execute(JanetArgs args) { static Janet os_execute(int32_t argc, Janet *argv) {
JANET_MINARITY(args, 1); janet_arity(argc, 1, -1);
JanetBuffer *buffer = janet_buffer(10); JanetBuffer *buffer = janet_buffer(10);
for (int32_t i = 0; i < args.n; i++) { for (int32_t i = 0; i < argc; i++) {
const uint8_t *argstring; const uint8_t *argstring = janet_getstring(argv, i);
JANET_ARG_STRING(argstring, args, i);
janet_buffer_push_bytes(buffer, argstring, janet_string_length(argstring)); janet_buffer_push_bytes(buffer, argstring, janet_string_length(argstring));
if (i != args.n - 1) { if (i != argc - 1) {
janet_buffer_push_u8(buffer, ' '); janet_buffer_push_u8(buffer, ' ');
} }
} }
@ -80,7 +81,7 @@ static int os_execute(JanetArgs args) {
buffer->count); buffer->count);
if (nwritten == 0) { if (nwritten == 0) {
free(sys_str); free(sys_str);
JANET_THROW(args, "could not create process"); janet_panic("could not create process");
} }
STARTUPINFO si; STARTUPINFO si;
@ -102,7 +103,7 @@ static int os_execute(JanetArgs args) {
&si, &si,
&pi)) { &pi)) {
free(sys_str); free(sys_str);
JANET_THROW(args, "could not create process"); janet_panic("could not create process");
} }
free(sys_str); free(sys_str);
@ -114,61 +115,57 @@ static int os_execute(JanetArgs args) {
GetExitCodeProcess(pi.hProcess, (LPDWORD)&status); GetExitCodeProcess(pi.hProcess, (LPDWORD)&status);
CloseHandle(pi.hProcess); CloseHandle(pi.hProcess);
CloseHandle(pi.hThread); CloseHandle(pi.hThread);
JANET_RETURN_INTEGER(args, (int32_t)status); return janet_wrap_integer(status);
} }
#else #else
static int os_execute(JanetArgs args) { static Janet os_execute(int32_t argc, Janet *argv) {
JANET_MINARITY(args, 1); janet_arity(argc, 1, -1);
const uint8_t **argv = malloc(sizeof(uint8_t *) * (args.n + 1)); const uint8_t **child_argv = malloc(sizeof(uint8_t *) * (argc + 1));
if (NULL == argv) { if (NULL == child_argv) {
JANET_OUT_OF_MEMORY; JANET_OUT_OF_MEMORY;
} }
for (int32_t i = 0; i < args.n; i++) { for (int32_t i = 0; i < argc; i++) {
JANET_ARG_STRING(argv[i], args, i); child_argv[i] = janet_getstring(argv, i);
} }
argv[args.n] = NULL; child_argv[argc] = NULL;
/* Fork child process */ /* Fork child process */
pid_t pid = fork(); pid_t pid = fork();
if (pid < 0) { if (pid < 0) {
JANET_THROW(args, "failed to execute"); janet_panic("failed to execute");
} else if (pid == 0) { } else if (pid == 0) {
if (-1 == execve((const char *)argv[0], (char **)argv, NULL)) { if (-1 == execve((const char *)child_argv[0], (char **)child_argv, NULL)) {
exit(1); exit(1);
} }
} }
int status; int status;
waitpid(pid, &status, 0); waitpid(pid, &status, 0);
JANET_RETURN_INTEGER(args, status); return janet_wrap_integer(status);
} }
#endif #endif
static int os_shell(JanetArgs args) { static Janet os_shell(int32_t argc, Janet *argv) {
int nofirstarg = (args.n < 1 || !janet_checktype(args.v[0], JANET_STRING)); janet_arity(argc, 0, 1);
const char *cmd = nofirstarg const char *cmd = argc
? NULL ? (const char *)janet_getstring(argv, 0)
: (const char *) janet_unwrap_string(args.v[0]); : NULL;
int stat = system(cmd); int stat = system(cmd);
JANET_RETURN(args, cmd return argc
? janet_wrap_integer(stat) ? janet_wrap_integer(stat)
: janet_wrap_boolean(stat)); : janet_wrap_boolean(stat);
} }
static int os_getenv(JanetArgs args) { static Janet os_getenv(int32_t argc, Janet *argv) {
const uint8_t *k; janet_arity(argc, 1, 1);
JANET_FIXARITY(args, 1); const uint8_t *k = janet_getstring(argv, 0);
JANET_ARG_STRING(k, args, 0);
const char *cstr = (const char *) k; const char *cstr = (const char *) k;
const char *res = getenv(cstr); const char *res = getenv(cstr);
if (!res) { return (res && cstr)
JANET_RETURN_NIL(args); ? janet_cstringv(res)
} : janet_wrap_nil();
JANET_RETURN(args, cstr
? janet_cstringv(res)
: janet_wrap_nil());
} }
static int os_setenv(JanetArgs args) { static Janet os_setenv(int32_t argc, Janet *argv) {
#ifdef JANET_WINDOWS #ifdef JANET_WINDOWS
#define SETENV(K,V) _putenv_s(K, V) #define SETENV(K,V) _putenv_s(K, V)
#define UNSETENV(K) _putenv_s(K, "") #define UNSETENV(K) _putenv_s(K, "")
@ -176,39 +173,35 @@ static int os_setenv(JanetArgs args) {
#define SETENV(K,V) setenv(K, V, 1) #define SETENV(K,V) setenv(K, V, 1)
#define UNSETENV(K) unsetenv(K) #define UNSETENV(K) unsetenv(K)
#endif #endif
const uint8_t *k; janet_arity(argc, 1, 2);
const char *ks; const uint8_t *k = janet_getstring(argv, 0);
JANET_MAXARITY(args, 2); const char *ks = (const char *) k;
JANET_MINARITY(args, 1); if (argc == 1 || janet_checktype(argv[1], JANET_NIL)) {
JANET_ARG_STRING(k, args, 0);
ks = (const char *) k;
if (args.n == 1 || janet_checktype(args.v[1], JANET_NIL)) {
UNSETENV(ks); UNSETENV(ks);
} else { } else {
const uint8_t *v; const uint8_t *v = janet_getstring(argv, 1);
JANET_ARG_STRING(v, args, 1); SETENV(ks, (const char *)v);
const char *vc = (const char *) v;
SETENV(ks, vc);
} }
return 0; return janet_wrap_nil();
} }
static int os_exit(JanetArgs args) { static Janet os_exit(int32_t argc, Janet *argv) {
JANET_MAXARITY(args, 1); janet_arity(argc, 0, 1);
if (args.n == 0) { if (argc == 0) {
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} else if (janet_checkint(args.v[0])) { } else if (janet_checkint(argv[0])) {
exit(janet_unwrap_integer(args.v[0])); exit(janet_unwrap_integer(argv[0]));
} else { } else {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
return 0; return janet_wrap_nil();
} }
static int os_time(JanetArgs args) { static Janet os_time(int32_t argc, Janet *argv) {
JANET_FIXARITY(args, 0); janet_arity(argc, 0, 0);
(void) argv;
double dtime = (double)(time(NULL)); double dtime = (double)(time(NULL));
JANET_RETURN_NUMBER(args, dtime); return janet_wrap_number(dtime);
} }
/* Clock shims */ /* Clock shims */
@ -238,22 +231,19 @@ static int gettime(struct timespec *spec) {
#define gettime(TV) clock_gettime(CLOCK_MONOTONIC, (TV)) #define gettime(TV) clock_gettime(CLOCK_MONOTONIC, (TV))
#endif #endif
static int os_clock(JanetArgs args) { static Janet os_clock(int32_t argc, Janet *argv) {
JANET_FIXARITY(args, 0); janet_arity(argc, 0, 0);
(void) argv;
struct timespec tv; struct timespec tv;
if (gettime(&tv)) if (gettime(&tv)) janet_panic("could not get time");
JANET_THROW(args, "could not get time");
double dtime = tv.tv_sec + (tv.tv_nsec / 1E9); double dtime = tv.tv_sec + (tv.tv_nsec / 1E9);
JANET_RETURN_NUMBER(args, dtime); return janet_wrap_number(dtime);
} }
static int os_sleep(JanetArgs args) { static Janet os_sleep(int32_t argc, Janet *argv) {
double delay; janet_arity(argc, 1, 1);
JANET_FIXARITY(args, 1); double delay = janet_getnumber(argv, 0);
JANET_ARG_NUMBER(delay, args, 0); if (delay < 0) janet_panic("invalid argument to sleep");
if (delay < 0) {
JANET_THROW(args, "invalid argument to sleep");
}
#ifdef JANET_WINDOWS #ifdef JANET_WINDOWS
Sleep((DWORD) (delay * 1000)); Sleep((DWORD) (delay * 1000));
#else #else
@ -264,11 +254,12 @@ static int os_sleep(JanetArgs args) {
: 0; : 0;
nanosleep(&ts, NULL); nanosleep(&ts, NULL);
#endif #endif
return 0; return janet_wrap_nil();
} }
static int os_cwd(JanetArgs args) { static Janet os_cwd(int32_t argc, Janet *argv) {
JANET_FIXARITY(args, 0); janet_arity(argc, 0, 0);
(void) argv;
char buf[FILENAME_MAX]; char buf[FILENAME_MAX];
char *ptr; char *ptr;
#ifdef JANET_WINDOWS #ifdef JANET_WINDOWS
@ -276,10 +267,8 @@ static int os_cwd(JanetArgs args) {
#else #else
ptr = getcwd(buf, FILENAME_MAX); ptr = getcwd(buf, FILENAME_MAX);
#endif #endif
if (NULL == ptr) { if (NULL == ptr) janet_panic("could not get current directory");
JANET_THROW(args, "could not get current directory"); return janet_cstringv(ptr);
}
JANET_RETURN_CSTRING(args, ptr);
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
@ -335,8 +324,6 @@ static const JanetReg cfuns[] = {
}; };
/* Module entry point */ /* Module entry point */
int janet_lib_os(JanetArgs args) { void janet_lib_os(JanetTable *env) {
JanetTable *env = janet_env(args);
janet_cfuns(env, NULL, cfuns); janet_cfuns(env, NULL, cfuns);
return 0;
} }

View File

@ -620,79 +620,58 @@ static JanetAbstractType janet_parse_parsertype = {
parsermark parsermark
}; };
JanetParser *janet_check_parser(Janet x) {
if (!janet_checktype(x, JANET_ABSTRACT))
return NULL;
void *abstract = janet_unwrap_abstract(x);
if (janet_abstract_type(abstract) != &janet_parse_parsertype)
return NULL;
return (JanetParser *)abstract;
}
/* C Function parser */ /* C Function parser */
static int cfun_parser(JanetArgs args) { static Janet cfun_parser(int32_t argc, Janet *argv) {
JANET_FIXARITY(args, 0); (void) argv;
janet_arity(argc, 0, 0);
JanetParser *p = janet_abstract(&janet_parse_parsertype, sizeof(JanetParser)); JanetParser *p = janet_abstract(&janet_parse_parsertype, sizeof(JanetParser));
janet_parser_init(p); janet_parser_init(p);
JANET_RETURN_ABSTRACT(args, p); return janet_wrap_abstract(p);
} }
static int cfun_consume(JanetArgs args) { static Janet cfun_consume(int32_t argc, Janet *argv) {
const uint8_t *bytes; janet_arity(argc, 2, 3);
int32_t len; JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
JanetParser *p; JanetByteView view = janet_getbytes(argv, 1);
int32_t i; if (argc == 3) {
JANET_MINARITY(args, 2); int32_t offset = janet_getinteger(argv, 2);
JANET_MAXARITY(args, 3); if (offset < 0 || offset > view.len)
JANET_CHECKABSTRACT(args, 0, &janet_parse_parsertype); janet_panicf("invalid offset %d out of range [0,%d]", offset, view.len);
p = (JanetParser *) janet_unwrap_abstract(args.v[0]); view.len -= offset;
JANET_ARG_BYTES(bytes, len, args, 1); view.bytes += offset;
if (args.n == 3) {
int32_t offset;
JANET_ARG_INTEGER(offset, args, 2);
if (offset < 0 || offset > len)
JANET_THROW(args, "invalid offset");
len -= offset;
bytes += offset;
} }
for (i = 0; i < len; i++) { int32_t i;
janet_parser_consume(p, bytes[i]); for (i = 0; i < view.len; i++) {
janet_parser_consume(p, view.bytes[i]);
switch (janet_parser_status(p)) { switch (janet_parser_status(p)) {
case JANET_PARSE_ROOT: case JANET_PARSE_ROOT:
case JANET_PARSE_PENDING: case JANET_PARSE_PENDING:
break; break;
default: default:
JANET_RETURN_INTEGER(args, i + 1); return janet_wrap_integer(i + 1);
} }
} }
JANET_RETURN_INTEGER(args, i); return janet_wrap_integer(i);
} }
static int cfun_has_more(JanetArgs args) { static Janet cfun_has_more(int32_t argc, Janet *argv) {
JanetParser *p; janet_arity(argc, 1, 1);
JANET_FIXARITY(args, 1); JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
JANET_CHECKABSTRACT(args, 0, &janet_parse_parsertype); return janet_wrap_boolean(janet_parser_has_more(p));
p = (JanetParser *) janet_unwrap_abstract(args.v[0]);
JANET_RETURN_BOOLEAN(args, janet_parser_has_more(p));
} }
static int cfun_byte(JanetArgs args) { static Janet cfun_byte(int32_t argc, Janet *argv) {
int32_t i; janet_arity(argc, 2, 2);
JanetParser *p; JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
JANET_FIXARITY(args, 2); int32_t i = janet_getinteger(argv, 1);
JANET_CHECKABSTRACT(args, 0, &janet_parse_parsertype);
p = (JanetParser *) janet_unwrap_abstract(args.v[0]);
JANET_ARG_INTEGER(i, args, 1);
janet_parser_consume(p, 0xFF & i); janet_parser_consume(p, 0xFF & i);
JANET_RETURN(args, args.v[0]); return argv[0];
} }
static int cfun_status(JanetArgs args) { static Janet cfun_status(int32_t argc, Janet *argv) {
janet_arity(argc, 1, 1);
JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
const char *stat = NULL; const char *stat = NULL;
JanetParser *p;
JANET_FIXARITY(args, 1);
JANET_CHECKABSTRACT(args, 0, &janet_parse_parsertype);
p = (JanetParser *) janet_unwrap_abstract(args.v[0]);
switch (janet_parser_status(p)) { switch (janet_parser_status(p)) {
case JANET_PARSE_PENDING: case JANET_PARSE_PENDING:
stat = "pending"; stat = "pending";
@ -704,58 +683,42 @@ static int cfun_status(JanetArgs args) {
stat = "root"; stat = "root";
break; break;
} }
JANET_RETURN_CKEYWORD(args, stat); return janet_ckeywordv(stat);
} }
static int cfun_error(JanetArgs args) { static Janet cfun_error(int32_t argc, Janet *argv) {
const char *err; janet_arity(argc, 1, 1);
JanetParser *p; JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
JANET_FIXARITY(args, 1); const char *err = janet_parser_error(p);
JANET_CHECKABSTRACT(args, 0, &janet_parse_parsertype); if (err) return janet_cstringv(err);
p = (JanetParser *) janet_unwrap_abstract(args.v[0]); return janet_wrap_nil();
err = janet_parser_error(p);
if (err) {
JANET_RETURN_CSTRING(args, err);
} else {
JANET_RETURN_NIL(args);
}
} }
static int cfun_produce(JanetArgs args) { static Janet cfun_produce(int32_t argc, Janet *argv) {
Janet val; janet_arity(argc, 1, 1);
JanetParser *p; JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
JANET_FIXARITY(args, 1); return janet_parser_produce(p);
JANET_CHECKABSTRACT(args, 0, &janet_parse_parsertype);
p = (JanetParser *) janet_unwrap_abstract(args.v[0]);
val = janet_parser_produce(p);
JANET_RETURN(args, val);
} }
static int cfun_flush(JanetArgs args) { static Janet cfun_flush(int32_t argc, Janet *argv) {
JanetParser *p; janet_arity(argc, 1, 1);
JANET_FIXARITY(args, 1); JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
JANET_CHECKABSTRACT(args, 0, &janet_parse_parsertype);
p = (JanetParser *) janet_unwrap_abstract(args.v[0]);
janet_parser_flush(p); janet_parser_flush(p);
JANET_RETURN(args, args.v[0]); return argv[0];
} }
static int cfun_where(JanetArgs args) { static Janet cfun_where(int32_t argc, Janet *argv) {
JanetParser *p; janet_arity(argc, 1, 1);
JANET_FIXARITY(args, 1); JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
JANET_CHECKABSTRACT(args, 0, &janet_parse_parsertype); return janet_wrap_integer(p->offset);
p = (JanetParser *) janet_unwrap_abstract(args.v[0]);
JANET_RETURN_INTEGER(args, p->offset);
} }
static int cfun_state(JanetArgs args) { static Janet cfun_state(int32_t argc, Janet *argv) {
size_t i; size_t i;
const uint8_t *str; const uint8_t *str;
size_t oldcount; size_t oldcount;
JanetParser *p; janet_arity(argc, 1, 1);
JANET_FIXARITY(args, 1); JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
JANET_CHECKABSTRACT(args, 0, &janet_parse_parsertype);
p = (JanetParser *) janet_unwrap_abstract(args.v[0]);
oldcount = p->bufcount; oldcount = p->bufcount;
for (i = 0; i < p->statecount; i++) { for (i = 0; i < p->statecount; i++) {
JanetParseState *s = p->states + i; JanetParseState *s = p->states + i;
@ -776,7 +739,7 @@ static int cfun_state(JanetArgs args) {
} }
str = janet_string(p->buf + oldcount, (int32_t)(p->bufcount - oldcount)); str = janet_string(p->buf + oldcount, (int32_t)(p->bufcount - oldcount));
p->bufcount = oldcount; p->bufcount = oldcount;
JANET_RETURN_STRING(args, str); return janet_wrap_string(str);
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
@ -843,8 +806,6 @@ static const JanetReg cfuns[] = {
}; };
/* Load the library */ /* Load the library */
int janet_lib_parse(JanetArgs args) { void janet_lib_parse(JanetTable *env) {
JanetTable *env = janet_env(args);
janet_cfuns(env, NULL, cfuns); janet_cfuns(env, NULL, cfuns);
return 0;
} }

View File

@ -825,185 +825,125 @@ static int32_t kmp_next(struct kmp_state *state) {
/* CFuns */ /* CFuns */
static int cfun_slice(JanetArgs args) { static Janet cfun_slice(int32_t argc, Janet *argv) {
const uint8_t *data; JanetRange range = janet_getslice(argc, argv);
int32_t len, start, end; JanetByteView view = janet_getbytes(argv, 0);
const uint8_t *ret; return janet_stringv(view.bytes + range.start, range.end - range.start);
JANET_MINARITY(args, 1);
JANET_MAXARITY(args, 3);
JANET_ARG_BYTES(data, len, args, 0);
/* Get start */
if (args.n < 2) {
start = 0;
} else {
JANET_ARG_INTEGER(start, args, 1);
}
/* Get end */
if (args.n < 3) {
end = -1;
} else {
JANET_ARG_INTEGER(end, args, 2);
}
if (start < 0) start = len + start;
if (end < 0) end = len + end + 1;
if (end < 0 || start < 0 || end > len || start > len)
JANET_THROW(args, "slice range out of bounds");
if (end >= start) {
ret = janet_string(data + start, end - start);
} else {
ret = janet_cstring("");
}
JANET_RETURN_STRING(args, ret);
} }
static int cfun_repeat(JanetArgs args) { static Janet cfun_repeat(int32_t argc, Janet *argv) {
const uint8_t *data; janet_arity(argc, 2, 2);
uint8_t *newbuf, *p, *end; JanetByteView view = janet_getbytes(argv, 0);
int32_t len, rep; int32_t rep = janet_getinteger(argv, 1);
int64_t mulres; if (rep < 0) janet_panic("expected non-negative number of repetitions");
JANET_FIXARITY(args, 2); if (rep == 0) return janet_cstringv("");
JANET_ARG_BYTES(data, len, args, 0); int64_t mulres = (int64_t) rep * view.len;
JANET_ARG_INTEGER(rep, args, 1); if (mulres > INT32_MAX) janet_panic("result string is too long");
if (rep < 0) { uint8_t *newbuf = janet_string_begin((int32_t) mulres);
JANET_THROW(args, "expected non-negative number of repetitions"); uint8_t *end = newbuf + mulres;
} else if (rep == 0) { uint8_t *p = newbuf;
JANET_RETURN_CSTRING(args, ""); for (p = newbuf; p < end; p += view.len) {
memcpy(p, view.bytes, view.len);
} }
mulres = (int64_t) rep * len; return janet_wrap_string(janet_string_end(newbuf));
if (mulres > INT32_MAX) {
JANET_THROW(args, "result string is too long");
}
newbuf = janet_string_begin((int32_t) mulres);
end = newbuf + mulres;
for (p = newbuf; p < end; p += len) {
memcpy(p, data, len);
}
JANET_RETURN_STRING(args, janet_string_end(newbuf));
} }
static int cfun_bytes(JanetArgs args) { static Janet cfun_bytes(int32_t argc, Janet *argv) {
const uint8_t *str; janet_arity(argc, 1, 1);
int32_t strlen, i; JanetByteView view = janet_getbytes(argv, 0);
Janet *tup; Janet *tup = janet_tuple_begin(view.len);
JANET_FIXARITY(args, 1);
JANET_ARG_BYTES(str, strlen, args, 0);
tup = janet_tuple_begin(strlen);
for (i = 0; i < strlen; i++) {
tup[i] = janet_wrap_integer((int32_t) str[i]);
}
JANET_RETURN_TUPLE(args, janet_tuple_end(tup));
}
static int cfun_frombytes(JanetArgs args) {
int32_t i; int32_t i;
uint8_t *buf; for (i = 0; i < view.len; i++) {
for (i = 0; i < args.n; i++) { tup[i] = janet_wrap_integer((int32_t) view.bytes[i]);
if (!janet_checkint(args.v[i])) {
JANET_THROW(args, "expected integer byte values");
}
} }
buf = janet_string_begin(args.n); return janet_wrap_tuple(janet_tuple_end(tup));
for (i = 0; i < args.n; i++) { }
int32_t c;
JANET_ARG_INTEGER(c, args, i); static Janet cfun_frombytes(int32_t argc, Janet *argv) {
int32_t i;
uint8_t *buf = janet_string_begin(argc);
for (i = 0; i < argc; i++) {
int32_t c = janet_getinteger(argv, i);
buf[i] = c & 0xFF; buf[i] = c & 0xFF;
} }
JANET_RETURN_STRING(args, janet_string_end(buf)); return janet_wrap_string(janet_string_end(buf));
} }
static int cfun_asciilower(JanetArgs args) { static Janet cfun_asciilower(int32_t argc, Janet *argv) {
const uint8_t *str; janet_arity(argc, 1, 1);
uint8_t *buf; JanetByteView view = janet_getbytes(argv, 0);
int32_t len, i; uint8_t *buf = janet_string_begin(view.len);
JANET_FIXARITY(args, 1); for (int32_t i = 0; i < view.len; i++) {
JANET_ARG_BYTES(str, len, args, 0); uint8_t c = view.bytes[i];
buf = janet_string_begin(len);
for (i = 0; i < len; i++) {
uint8_t c = str[i];
if (c >= 65 && c <= 90) { if (c >= 65 && c <= 90) {
buf[i] = c + 32; buf[i] = c + 32;
} else { } else {
buf[i] = c; buf[i] = c;
} }
} }
JANET_RETURN_STRING(args, janet_string_end(buf)); return janet_wrap_string(janet_string_end(buf));
} }
static int cfun_asciiupper(JanetArgs args) { static Janet cfun_asciiupper(int32_t argc, Janet *argv) {
const uint8_t *str; janet_arity(argc, 1, 1);
uint8_t *buf; JanetByteView view = janet_getbytes(argv, 0);
int32_t len, i; uint8_t *buf = janet_string_begin(view.len);
JANET_FIXARITY(args, 1); for (int32_t i = 0; i < view.len; i++) {
JANET_ARG_BYTES(str, len, args, 0); uint8_t c = view.bytes[i];
buf = janet_string_begin(len);
for (i = 0; i < len; i++) {
uint8_t c = str[i];
if (c >= 97 && c <= 122) { if (c >= 97 && c <= 122) {
buf[i] = c - 32; buf[i] = c - 32;
} else { } else {
buf[i] = c; buf[i] = c;
} }
} }
JANET_RETURN_STRING(args, janet_string_end(buf)); return janet_wrap_string(janet_string_end(buf));
} }
static int cfun_reverse(JanetArgs args) { static Janet cfun_reverse(int32_t argc, Janet *argv) {
const uint8_t *str; janet_arity(argc, 1, 1);
uint8_t *buf; JanetByteView view = janet_getbytes(argv, 0);
int32_t len, i, j; uint8_t *buf = janet_string_begin(view.len);
JANET_FIXARITY(args, 1); int32_t i, j;
JANET_ARG_BYTES(str, len, args, 0); for (i = 0, j = view.len - 1; i < view.len; i++, j--) {
buf = janet_string_begin(len); buf[i] = view.bytes[j];
for (i = 0, j = len - 1; i < len; i++, j--) {
buf[i] = str[j];
} }
JANET_RETURN_STRING(args, janet_string_end(buf)); return janet_wrap_string(janet_string_end(buf));
} }
static int findsetup(JanetArgs args, struct kmp_state *s, int32_t extra) { static void findsetup(int32_t argc, Janet *argv, struct kmp_state *s, int32_t extra) {
const uint8_t *text, *pat; janet_arity(argc, 2, 3 + extra);
int32_t textlen, patlen, start; JanetByteView pat = janet_getbytes(argv, 0);
JANET_MINARITY(args, 2); JanetByteView text = janet_getbytes(argv, 1);
JANET_MAXARITY(args, 3 + extra); int32_t start = 0;
JANET_ARG_BYTES(pat, patlen, args, 0); if (argc >= 3) {
JANET_ARG_BYTES(text, textlen, args, 1); start = janet_getinteger(argv, 2);
if (args.n >= 3) { if (start < 0) janet_panic("expected non-negative start index");
JANET_ARG_INTEGER(start, args, 2);
if (start < 0) {
JANET_THROW(args, "expected non-negative start index");
}
} else {
start = 0;
} }
kmp_init(s, text, textlen, pat, patlen); kmp_init(s, text.bytes, text.len, pat.bytes, pat.len);
s->i = start; s->i = start;
return JANET_SIGNAL_OK;
} }
static int cfun_find(JanetArgs args) { static Janet cfun_find(int32_t argc, Janet *argv) {
int32_t result; int32_t result;
struct kmp_state state; struct kmp_state state;
int status = findsetup(args, &state, 0); findsetup(argc, argv, &state, 0);
if (status) return status;
result = kmp_next(&state); result = kmp_next(&state);
kmp_deinit(&state); kmp_deinit(&state);
JANET_RETURN(args, result < 0 return result < 0
? janet_wrap_nil() ? janet_wrap_nil()
: janet_wrap_integer(result)); : janet_wrap_integer(result);
} }
static int cfun_findall(JanetArgs args) { static Janet cfun_findall(int32_t argc, Janet *argv) {
int32_t result; int32_t result;
JanetArray *array;
struct kmp_state state; struct kmp_state state;
int status = findsetup(args, &state, 0); findsetup(argc, argv, &state, 0);
if (status) return status; JanetArray *array = janet_array(0);
array = janet_array(0);
while ((result = kmp_next(&state)) >= 0) { while ((result = kmp_next(&state)) >= 0) {
janet_array_push(array, janet_wrap_integer(result)); janet_array_push(array, janet_wrap_integer(result));
} }
kmp_deinit(&state); kmp_deinit(&state);
JANET_RETURN_ARRAY(args, array); return janet_wrap_array(array);
} }
struct replace_state { struct replace_state {
@ -1012,39 +952,31 @@ struct replace_state {
int32_t substlen; int32_t substlen;
}; };
static int replacesetup(JanetArgs args, struct replace_state *s) { static void replacesetup(int32_t argc, Janet *argv, struct replace_state *s) {
const uint8_t *text, *pat, *subst; janet_arity(argc, 3, 4);
int32_t textlen, patlen, substlen, start; JanetByteView pat = janet_getbytes(argv, 0);
JANET_MINARITY(args, 3); JanetByteView subst = janet_getbytes(argv, 1);
JANET_MAXARITY(args, 4); JanetByteView text = janet_getbytes(argv, 2);
JANET_ARG_BYTES(pat, patlen, args, 0); int32_t start = 0;
JANET_ARG_BYTES(subst, substlen, args, 1); if (argc == 4) {
JANET_ARG_BYTES(text, textlen, args, 2); start = janet_getinteger(argv, 3);
if (args.n == 4) { if (start < 0) janet_panic("expected non-negative start index");
JANET_ARG_INTEGER(start, args, 3);
if (start < 0) {
JANET_THROW(args, "expected non-negative start index");
}
} else {
start = 0;
} }
kmp_init(&s->kmp, text, textlen, pat, patlen); kmp_init(&s->kmp, text.bytes, text.len, pat.bytes, pat.len);
s->kmp.i = start; s->kmp.i = start;
s->subst = subst; s->subst = subst.bytes;
s->substlen = substlen; s->substlen = subst.len;
return JANET_SIGNAL_OK;
} }
static int cfun_replace(JanetArgs args) { static Janet cfun_replace(int32_t argc, Janet *argv) {
int32_t result; int32_t result;
struct replace_state s; struct replace_state s;
uint8_t *buf; uint8_t *buf;
int status = replacesetup(args, &s); replacesetup(argc, argv, &s);
if (status) return status;
result = kmp_next(&s.kmp); result = kmp_next(&s.kmp);
if (result < 0) { if (result < 0) {
kmp_deinit(&s.kmp); kmp_deinit(&s.kmp);
JANET_RETURN_STRING(args, janet_string(s.kmp.text, s.kmp.textlen)); return janet_stringv(s.kmp.text, s.kmp.textlen);
} }
buf = janet_string_begin(s.kmp.textlen - s.kmp.patlen + s.substlen); buf = janet_string_begin(s.kmp.textlen - s.kmp.patlen + s.substlen);
memcpy(buf, s.kmp.text, result); memcpy(buf, s.kmp.text, result);
@ -1053,17 +985,15 @@ static int cfun_replace(JanetArgs args) {
s.kmp.text + result + s.kmp.patlen, s.kmp.text + result + s.kmp.patlen,
s.kmp.textlen - result - s.kmp.patlen); s.kmp.textlen - result - s.kmp.patlen);
kmp_deinit(&s.kmp); kmp_deinit(&s.kmp);
JANET_RETURN_STRING(args, janet_string_end(buf)); return janet_wrap_string(janet_string_end(buf));
} }
static int cfun_replaceall(JanetArgs args) { static Janet cfun_replaceall(int32_t argc, Janet *argv) {
int32_t result; int32_t result;
struct replace_state s; struct replace_state s;
JanetBuffer b; JanetBuffer b;
const uint8_t *ret;
int32_t lastindex = 0; int32_t lastindex = 0;
int status = replacesetup(args, &s); replacesetup(argc, argv, &s);
if (status) return status;
janet_buffer_init(&b, s.kmp.textlen); janet_buffer_init(&b, s.kmp.textlen);
while ((result = kmp_next(&s.kmp)) >= 0) { while ((result = kmp_next(&s.kmp)) >= 0) {
janet_buffer_push_bytes(&b, s.kmp.text + lastindex, result - lastindex); janet_buffer_push_bytes(&b, s.kmp.text + lastindex, result - lastindex);
@ -1072,22 +1002,21 @@ static int cfun_replaceall(JanetArgs args) {
kmp_seti(&s.kmp, lastindex); kmp_seti(&s.kmp, lastindex);
} }
janet_buffer_push_bytes(&b, s.kmp.text + lastindex, s.kmp.textlen - lastindex); janet_buffer_push_bytes(&b, s.kmp.text + lastindex, s.kmp.textlen - lastindex);
ret = janet_string(b.data, b.count); const uint8_t *ret = janet_string(b.data, b.count);
janet_buffer_deinit(&b); janet_buffer_deinit(&b);
kmp_deinit(&s.kmp); kmp_deinit(&s.kmp);
JANET_RETURN_STRING(args, ret); return janet_wrap_string(ret);
} }
static int cfun_split(JanetArgs args) { static Janet cfun_split(int32_t argc, Janet *argv) {
int32_t result; int32_t result;
JanetArray *array; JanetArray *array;
struct kmp_state state; struct kmp_state state;
int32_t limit = -1, lastindex = 0; int32_t limit = -1, lastindex = 0;
if (args.n == 4) { if (argc == 4) {
JANET_ARG_INTEGER(limit, args, 3); limit = janet_getinteger(argv, 3);
} }
int status = findsetup(args, &state, 1); findsetup(argc, argv, &state, 1);
if (status) return status;
array = janet_array(0); array = janet_array(0);
while ((result = kmp_next(&state)) >= 0 && limit--) { while ((result = kmp_next(&state)) >= 0 && limit--) {
const uint8_t *slice = janet_string(state.text + lastindex, result - lastindex); const uint8_t *slice = janet_string(state.text + lastindex, result - lastindex);
@ -1099,80 +1028,75 @@ static int cfun_split(JanetArgs args) {
janet_array_push(array, janet_wrap_string(slice)); janet_array_push(array, janet_wrap_string(slice));
} }
kmp_deinit(&state); kmp_deinit(&state);
JANET_RETURN_ARRAY(args, array); return janet_wrap_array(array);
} }
static int cfun_checkset(JanetArgs args) { static Janet cfun_checkset(int32_t argc, Janet *argv) {
const uint8_t *set, *str;
int32_t setlen, strlen, i;
uint32_t bitset[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint32_t bitset[8] = {0, 0, 0, 0, 0, 0, 0, 0};
JANET_MINARITY(args, 2); janet_arity(argc, 2, 3);
JANET_MAXARITY(args, 3); JanetByteView set = janet_getbytes(argv, 0);
JANET_ARG_BYTES(set, setlen, args, 0); JanetByteView str = janet_getbytes(argv, 1);
JANET_ARG_BYTES(str, strlen, args, 1);
/* Populate set */ /* Populate set */
for (i = 0; i < setlen; i++) { for (int32_t i = 0; i < set.len; i++) {
int index = set[i] >> 5; int index = set.bytes[i] >> 5;
uint32_t mask = 1 << (set[i] & 7); uint32_t mask = 1 << (set.bytes[i] & 7);
bitset[index] |= mask; bitset[index] |= mask;
} }
if (args.n == 3) { if (argc == 3) {
int invert; if (janet_getboolean(argv, 2)) {
JANET_ARG_BOOLEAN(invert, args, 2); for (int i = 0; i < 8; i++)
if (invert) {
for (i = 0; i < 8; i++)
bitset[i] = ~bitset[i]; bitset[i] = ~bitset[i];
} }
} }
/* Check set */ /* Check set */
for (i = 0; i < strlen; i++) { for (int32_t i = 0; i < str.len; i++) {
int index = str[i] >> 5; int index = str.bytes[i] >> 5;
uint32_t mask = 1 << (str[i] & 7); uint32_t mask = 1 << (str.bytes[i] & 7);
if (!(bitset[index] & mask)) { if (!(bitset[index] & mask)) {
JANET_RETURN_FALSE(args); return janet_wrap_false();
} }
} }
JANET_RETURN_TRUE(args); return janet_wrap_true();
} }
static int cfun_join(JanetArgs args) { static Janet cfun_join(int32_t argc, Janet *argv) {
const Janet *parts; janet_arity(argc, 1, 2);
const uint8_t *joiner; JanetView parts = janet_getindexed(argv, 0);
uint8_t *buf, *out; JanetByteView joiner;
int32_t joinerlen, partslen, finallen, i; if (argc == 2) {
JANET_MINARITY(args, 1); joiner = janet_getbytes(argv, 1);
JANET_MAXARITY(args, 2);
JANET_ARG_INDEXED(parts, partslen, args, 0);
if (args.n == 2) {
JANET_ARG_BYTES(joiner, joinerlen, args, 1);
} else { } else {
joiner = NULL; joiner.bytes = NULL;
joinerlen = 0; joiner.len = 0;
} }
/* Check args */ /* Check args */
finallen = 0; int32_t i;
for (i = 0; i < partslen; i++) { int64_t finallen = 0;
for (i = 0; i < parts.len; i++) {
const uint8_t *chunk; const uint8_t *chunk;
int32_t chunklen = 0; int32_t chunklen = 0;
if (!janet_bytes_view(parts[i], &chunk, &chunklen)) { if (!janet_bytes_view(parts.items[i], &chunk, &chunklen)) {
JANET_THROW(args, "expected string|symbol|buffer"); janet_panicf("item %d of parts is not a byte sequence, got %v", i, parts.items[i]);
} }
if (i) finallen += joinerlen; if (i) finallen += joiner.len;
finallen += chunklen; finallen += chunklen;
if (finallen > INT32_MAX)
janet_panic("result string too long");
} }
uint8_t *buf, *out;
out = buf = janet_string_begin(finallen); out = buf = janet_string_begin(finallen);
for (i = 0; i < partslen; i++) { for (i = 0; i < parts.len; i++) {
const uint8_t *chunk = NULL; const uint8_t *chunk = NULL;
int32_t chunklen = 0; int32_t chunklen = 0;
if (i) { if (i) {
memcpy(out, joiner, joinerlen); memcpy(out, joiner.bytes, joiner.len);
out += joinerlen; out += joiner.len;
} }
janet_bytes_view(parts[i], &chunk, &chunklen); janet_bytes_view(parts.items[i], &chunk, &chunklen);
memcpy(out, chunk, chunklen); memcpy(out, chunk, chunklen);
out += chunklen; out += chunklen;
} }
JANET_RETURN_STRING(args, janet_string_end(buf)); return janet_wrap_string(janet_string_end(buf));
} }
static struct formatter { static struct formatter {
@ -1188,29 +1112,29 @@ static struct formatter {
{"F", "%F", "%.*F"} {"F", "%F", "%.*F"}
}; };
static int cfun_number(JanetArgs args) { static Janet cfun_number(int32_t argc, Janet *argv) {
janet_arity(argc, 1, 4);
double x = janet_getnumber(argv, 0);
struct formatter fmter = formatters[0]; struct formatter fmter = formatters[0];
char buf[100]; char buf[100];
double x;
int formatNargs = 1; int formatNargs = 1;
int32_t precision = 0; int32_t precision = 0;
JANET_MINARITY(args, 1); if (argc >= 2) {
JANET_MAXARITY(args, 4); const uint8_t *flag = janet_getkeyword(argv, 1);
JANET_ARG_NUMBER(x, args, 0); int i;
if (args.n >= 2) { for (i = 0; i < 6; i++) {
const uint8_t *flag;
JANET_ARG_KEYWORD(flag, args, 1);
for (int i = 0; i < 6; i++) {
struct formatter fmttest = formatters[i]; struct formatter fmttest = formatters[i];
if (!janet_cstrcmp(flag, fmttest.lead)) { if (!janet_cstrcmp(flag, fmttest.lead)) {
fmter = fmttest; fmter = fmttest;
break; break;
} }
} }
if (i == 6)
janet_panicf("unsupported formatter %v", argv[1]);
} }
if (args.n >= 3) { if (argc >= 3) {
JANET_ARG_INTEGER(precision, args, 2); precision = janet_getinteger(argv, 2);
formatNargs++; formatNargs++;
} }
@ -1220,20 +1144,19 @@ static int cfun_number(JanetArgs args) {
snprintf(buf, sizeof(buf), fmter.f2, precision, x); snprintf(buf, sizeof(buf), fmter.f2, precision, x);
} }
JANET_RETURN_CSTRING(args, buf); return janet_cstringv(buf);
} }
static int cfun_pretty(JanetArgs args) { static Janet cfun_pretty(int32_t argc, Janet *argv) {
janet_arity(argc, 1, 3);
JanetBuffer *buffer = NULL; JanetBuffer *buffer = NULL;
int32_t depth = 4; int32_t depth = 4;
JANET_MINARITY(args, 1); if (argc > 1)
JANET_MAXARITY(args, 3); depth = janet_getinteger(argv, 1);
if (args.n > 1) if (argc > 2)
JANET_ARG_INTEGER(depth, args, 1); buffer = janet_getbuffer(argv, 2);
if (args.n > 2) buffer = janet_pretty(buffer, depth, argv[0]);
JANET_ARG_BUFFER(buffer, args, 2); return janet_wrap_buffer(buffer);
buffer = janet_pretty(buffer, depth, args.v[0]);
JANET_RETURN_BUFFER(args, buffer);
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
@ -1337,8 +1260,6 @@ static const JanetReg cfuns[] = {
}; };
/* Module entry point */ /* Module entry point */
int janet_lib_string(JanetArgs args) { void janet_lib_string(JanetTable *env) {
JanetTable *env = janet_env(args);
janet_cfuns(env, NULL, cfuns); janet_cfuns(env, NULL, cfuns);
return 0;
} }

View File

@ -163,8 +163,7 @@ const JanetKV *janet_table_next(JanetTable *t, const JanetKV *kv) {
JanetKV *end = t->data + t->capacity; JanetKV *end = t->data + t->capacity;
kv = (kv == NULL) ? t->data : kv + 1; kv = (kv == NULL) ? t->data : kv + 1;
while (kv < end) { while (kv < end) {
if (!janet_checktype(kv->key, JANET_NIL)) if (!janet_checktype(kv->key, JANET_NIL)) return kv;
return kv;
kv++; kv++;
} }
return NULL; return NULL;
@ -206,49 +205,41 @@ void janet_table_merge_struct(JanetTable *table, const JanetKV *other) {
/* C Functions */ /* C Functions */
static int cfun_new(JanetArgs args) { static Janet cfun_new(int32_t argc, Janet *argv) {
JanetTable *t; janet_arity(argc, 1, 1);
int32_t cap; int32_t cap = janet_getinteger(argv, 0);
JANET_FIXARITY(args, 1); return janet_wrap_table(janet_table(cap));
JANET_ARG_INTEGER(cap, args, 0);
t = janet_table(cap);
JANET_RETURN_TABLE(args, t);
} }
static int cfun_getproto(JanetArgs args) { static Janet cfun_getproto(int32_t argc, Janet *argv) {
JanetTable *t; janet_arity(argc, 1, 1);
JANET_FIXARITY(args, 1); JanetTable *t = janet_gettable(argv, 0);
JANET_ARG_TABLE(t, args, 0); return t->proto
JANET_RETURN(args, t->proto ? janet_wrap_table(t->proto)
? janet_wrap_table(t->proto) : janet_wrap_nil();
: janet_wrap_nil());
} }
static int cfun_setproto(JanetArgs args) { static Janet cfun_setproto(int32_t argc, Janet *argv) {
JanetTable *table, *proto; janet_arity(argc, 2, 2);
JANET_FIXARITY(args, 2); JanetTable *table = janet_gettable(argv, 0);
JANET_ARG_TABLE(table, args, 0); JanetTable *proto = NULL;
if (janet_checktype(args.v[1], JANET_NIL)) { if (!janet_checktype(argv[1], JANET_NIL)) {
proto = NULL; proto = janet_gettable(argv, 1);
} else {
JANET_ARG_TABLE(proto, args, 1);
} }
table->proto = proto; table->proto = proto;
JANET_RETURN_TABLE(args, table); return argv[0];
} }
static int cfun_tostruct(JanetArgs args) { static Janet cfun_tostruct(int32_t argc, Janet *argv) {
JanetTable *t; janet_arity(argc, 1, 1);
JANET_FIXARITY(args, 1); JanetTable *t = janet_gettable(argv, 0);
JANET_ARG_TABLE(t, args, 0); return janet_wrap_struct(janet_table_to_struct(t));
JANET_RETURN_STRUCT(args, janet_table_to_struct(t));
} }
static int cfun_rawget(JanetArgs args) { static Janet cfun_rawget(int32_t argc, Janet *argv) {
JanetTable *table; janet_arity(argc, 2, 2);
JANET_FIXARITY(args, 2); JanetTable *table = janet_gettable(argv, 0);
JANET_ARG_TABLE(table, args, 0); return janet_table_rawget(table, argv[1]);
JANET_RETURN(args, janet_table_rawget(table, args.v[1]));
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
@ -283,10 +274,6 @@ static const JanetReg cfuns[] = {
}; };
/* Load the table module */ /* Load the table module */
int janet_lib_table(JanetArgs args) { void janet_lib_table(JanetTable *env) {
JanetTable *env = janet_env(args);
janet_cfuns(env, NULL, cfuns); janet_cfuns(env, NULL, cfuns);
return 0;
} }
#undef janet_maphash

View File

@ -91,64 +91,30 @@ int janet_tuple_compare(const Janet *lhs, const Janet *rhs) {
/* C Functions */ /* C Functions */
static int cfun_slice(JanetArgs args) { static Janet cfun_slice(int32_t argc, Janet *argv) {
const Janet *vals; JanetRange range = janet_getslice(argc, argv);
int32_t len; JanetView view = janet_getindexed(argv, 0);
Janet *ret; return janet_wrap_tuple(janet_tuple_n(view.items + range.start, range.end - range.start));
int32_t start, end;
JANET_MINARITY(args, 1);
if (!janet_indexed_view(args.v[0], &vals, &len)) JANET_THROW(args, "expected array/tuple");
/* Get start */
if (args.n < 2) {
start = 0;
} else {
JANET_ARG_INTEGER(start, args, 1);
}
/* Get end */
if (args.n < 3) {
end = -1;
} else {
JANET_ARG_INTEGER(end, args, 2);
}
if (start < 0) start = len + start;
if (end < 0) end = len + end + 1;
if (end < 0 || start < 0 || end > len || start > len)
JANET_THROW(args, "slice range out of bounds");
if (end >= start) {
ret = janet_tuple_begin(end - start);
memcpy(ret, vals + start, sizeof(Janet) * (end - start));
} else {
ret = janet_tuple_begin(0);
}
JANET_RETURN_TUPLE(args, janet_tuple_end(ret));
} }
static int cfun_prepend(JanetArgs args) { static Janet cfun_prepend(int32_t argc, Janet *argv) {
const Janet *t; janet_arity(argc, 1, -1);
int32_t len, i; JanetView view = janet_getindexed(argv, 0);
Janet *n; Janet *n = janet_tuple_begin(view.len - 1 + argc);
JANET_MINARITY(args, 1); memcpy(n - 1 + argc, view.items, sizeof(Janet) * view.len);
if (!janet_indexed_view(args.v[0], &t, &len)) for (int32_t i = 1; i < argc; i++) {
JANET_THROW(args, "expected tuple/array"); n[argc - i - 1] = argv[i];
n = janet_tuple_begin(len - 1 + args.n);
memcpy(n - 1 + args.n, t, sizeof(Janet) * len);
for (i = 1; i < args.n; i++) {
n[args.n - i - 1] = args.v[i];
} }
JANET_RETURN_TUPLE(args, janet_tuple_end(n)); return janet_wrap_tuple(janet_tuple_end(n));
} }
static int cfun_append(JanetArgs args) { static Janet cfun_append(int32_t argc, Janet *argv) {
const Janet *t; janet_arity(argc, 1, -1);
int32_t len; JanetView view = janet_getindexed(argv, 0);
Janet *n; Janet *n = janet_tuple_begin(view.len - 1 + argc);
JANET_MINARITY(args, 1); memcpy(n, view.items, sizeof(Janet) * view.len);
if (!janet_indexed_view(args.v[0], &t, &len)) memcpy(n + view.len, argv + 1, sizeof(Janet) * (argc - 1));
JANET_THROW(args, "expected tuple/array"); return janet_wrap_tuple(janet_tuple_end(n));
n = janet_tuple_begin(len - 1 + args.n);
memcpy(n, t, sizeof(Janet) * len);
memcpy(n + len, args.v + 1, sizeof(Janet) * (args.n - 1));
JANET_RETURN_TUPLE(args, janet_tuple_end(n));
} }
static const JanetReg cfuns[] = { static const JanetReg cfuns[] = {
@ -174,8 +140,6 @@ static const JanetReg cfuns[] = {
}; };
/* Load the tuple module */ /* Load the tuple module */
int janet_lib_tuple(JanetArgs args) { void janet_lib_tuple(JanetTable *env) {
JanetTable *env = janet_env(args);
janet_cfuns(env, NULL, cfuns); janet_cfuns(env, NULL, cfuns);
return 0;
} }

View File

@ -304,18 +304,6 @@ JanetBindingType janet_resolve(JanetTable *env, const uint8_t *sym, Janet *out)
return JANET_BINDING_DEF; return JANET_BINDING_DEF;
} }
/* Get module from the arguments passed to library */
JanetTable *janet_env(JanetArgs args) {
JanetTable *module;
if (args.n >= 1 && janet_checktype(args.v[0], JANET_TABLE)) {
module = janet_unwrap_table(args.v[0]);
} else {
module = janet_table(0);
}
*args.ret = janet_wrap_table(module);
return module;
}
/* Read both tuples and arrays as c pointers + int32_t length. Return 1 if the /* Read both tuples and arrays as c pointers + int32_t length. Return 1 if the
* view can be constructed, 0 if an invalid type. */ * view can be constructed, 0 if an invalid type. */
int janet_indexed_view(Janet seq, const Janet **data, int32_t *len) { int janet_indexed_view(Janet seq, const Janet **data, int32_t *len) {
@ -365,67 +353,6 @@ int janet_dictionary_view(Janet tab, const JanetKV **data, int32_t *len, int32_t
return 0; return 0;
} }
/* Get actual type name of a value for debugging purposes */
static const char *typestr(JanetArgs args, int32_t n) {
JanetType actual = n < args.n ? janet_type(args.v[n]) : JANET_NIL;
return ((actual == JANET_ABSTRACT)
? janet_abstract_type(janet_unwrap_abstract(args.v[n]))->name
: janet_type_names[actual]);
}
int janet_type_err(JanetArgs args, int32_t n, JanetType expected) {
const uint8_t *message = janet_formatc(
"bad slot #%d, expected %t, got %s",
n,
expected,
typestr(args, n));
JANET_THROWV(args, janet_wrap_string(message));
}
void janet_buffer_push_types(JanetBuffer *buffer, int types) {
int first = 1;
int i = 0;
while (types) {
if (1 & types) {
if (first) {
first = 0;
} else {
janet_buffer_push_u8(buffer, '|');
}
janet_buffer_push_cstring(buffer, janet_type_names[i]);
}
i++;
types >>= 1;
}
}
int janet_typemany_err(JanetArgs args, int32_t n, int expected) {
const uint8_t *message;
JanetBuffer buf;
janet_buffer_init(&buf, 20);
janet_buffer_push_string(&buf, janet_formatc("bad slot #%d, expected ", n));
janet_buffer_push_types(&buf, expected);
janet_buffer_push_cstring(&buf, ", got ");
janet_buffer_push_cstring(&buf, typestr(args, n));
message = janet_string(buf.data, buf.count);
janet_buffer_deinit(&buf);
JANET_THROWV(args, janet_wrap_string(message));
}
int janet_arity_err(JanetArgs args, int32_t n, const char *prefix) {
JANET_THROWV(args,
janet_wrap_string(janet_formatc(
"expected %s%d argument%s, got %d",
prefix, n, n == 1 ? "" : "s", args.n)));
}
int janet_typeabstract_err(JanetArgs args, int32_t n, const JanetAbstractType *at) {
JANET_THROWV(args,
janet_wrap_string(janet_formatc(
"bad slot #%d, expected %s, got %s",
n, at->name, typestr(args, n))));
}
int janet_checkint(Janet x) { int janet_checkint(Janet x) {
if (!janet_checktype(x, JANET_NUMBER)) if (!janet_checktype(x, JANET_NUMBER))
return 0; return 0;

View File

@ -44,21 +44,21 @@ const void *janet_strbinsearch(
const uint8_t *key); const uint8_t *key);
/* Initialize builtin libraries */ /* Initialize builtin libraries */
int janet_lib_io(JanetArgs args); void janet_lib_io(JanetTable *env);
int janet_lib_math(JanetArgs args); void janet_lib_math(JanetTable *env);
int janet_lib_array(JanetArgs args); void janet_lib_array(JanetTable *env);
int janet_lib_tuple(JanetArgs args); void janet_lib_tuple(JanetTable *env);
int janet_lib_buffer(JanetArgs args); void janet_lib_buffer(JanetTable *env);
int janet_lib_table(JanetArgs args); void janet_lib_table(JanetTable *env);
int janet_lib_fiber(JanetArgs args); void janet_lib_fiber(JanetTable *env);
int janet_lib_os(JanetArgs args); void janet_lib_os(JanetTable *env);
int janet_lib_string(JanetArgs args); void janet_lib_string(JanetTable *env);
int janet_lib_marsh(JanetArgs args); void janet_lib_marsh(JanetTable *env);
int janet_lib_parse(JanetArgs args); void janet_lib_parse(JanetTable *env);
#ifdef JANET_ASSEMBLER #ifdef JANET_ASSEMBLER
int janet_lib_asm(JanetArgs args); void janet_lib_asm(JanetTable *env);
#endif #endif
int janet_lib_compile(JanetArgs args); void janet_lib_compile(JanetTable *env);
int janet_lib_debug(JanetArgs args); void janet_lib_debug(JanetTable *env);
#endif #endif

View File

@ -572,18 +572,14 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
pc = func->def->bytecode; pc = func->def->bytecode;
vm_checkgc_next(); vm_checkgc_next();
} else if (janet_checktype(callee, JANET_CFUNCTION)) { } else if (janet_checktype(callee, JANET_CFUNCTION)) {
JanetArgs args;
Janet retreg = janet_wrap_nil();
vm_commit(); vm_commit();
args.n = fiber->stacktop - fiber->stackstart; int32_t argc = fiber->stacktop - fiber->stackstart;
janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee)); janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee));
args.v = fiber->data + fiber->frame; Janet ret = janet_unwrap_cfunction(callee)(argc, fiber->data + fiber->frame);
args.ret = &retreg;
if (janet_unwrap_cfunction(callee)(args)) janet_panicv(retreg);
janet_fiber_popframe(fiber); janet_fiber_popframe(fiber);
if (fiber->frame == 0) vm_return(JANET_SIGNAL_OK, retreg); if (fiber->frame == 0) vm_return(JANET_SIGNAL_OK, ret);
stack = fiber->data + fiber->frame; stack = fiber->data + fiber->frame;
stack[A] = retreg; stack[A] = ret;
vm_checkgc_pcnext(); vm_checkgc_pcnext();
} else { } else {
vm_commit(); vm_commit();
@ -606,19 +602,14 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
pc = func->def->bytecode; pc = func->def->bytecode;
vm_checkgc_next(); vm_checkgc_next();
} else { } else {
Janet retreg = janet_wrap_nil(); Janet retreg;
vm_commit();
if (janet_checktype(callee, JANET_CFUNCTION)) { if (janet_checktype(callee, JANET_CFUNCTION)) {
JanetArgs args; int32_t argc = fiber->stacktop - fiber->stackstart;
vm_commit();
args.n = fiber->stacktop - fiber->stackstart;
janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee)); janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee));
args.v = fiber->data + fiber->frame; retreg = janet_unwrap_cfunction(callee)(argc, fiber->data + fiber->frame);
args.ret = &retreg;
if (janet_unwrap_cfunction(callee)(args))
vm_return(JANET_SIGNAL_ERROR, retreg);
janet_fiber_popframe(fiber); janet_fiber_popframe(fiber);
} else { } else {
vm_commit();
retreg = call_nonfn(fiber, callee); retreg = call_nonfn(fiber, callee);
} }
janet_fiber_popframe(fiber); janet_fiber_popframe(fiber);
@ -653,22 +644,27 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
} }
VM_OP(JOP_PUT) VM_OP(JOP_PUT)
vm_commit();
janet_put(stack[A], stack[B], stack[C]); janet_put(stack[A], stack[B], stack[C]);
vm_checkgc_pcnext(); vm_checkgc_pcnext();
VM_OP(JOP_PUT_INDEX) VM_OP(JOP_PUT_INDEX)
vm_commit();
janet_putindex(stack[A], C, stack[B]); janet_putindex(stack[A], C, stack[B]);
vm_checkgc_pcnext(); vm_checkgc_pcnext();
VM_OP(JOP_GET) VM_OP(JOP_GET)
vm_commit();
stack[A] = janet_get(stack[B], stack[C]); stack[A] = janet_get(stack[B], stack[C]);
vm_pcnext(); vm_pcnext();
VM_OP(JOP_GET_INDEX) VM_OP(JOP_GET_INDEX)
vm_commit();
stack[A] = janet_getindex(stack[B], C); stack[A] = janet_getindex(stack[B], C);
vm_pcnext(); vm_pcnext();
VM_OP(JOP_LENGTH) VM_OP(JOP_LENGTH)
vm_commit();
stack[A] = janet_wrap_integer(janet_length(stack[E])); stack[A] = janet_wrap_integer(janet_length(stack[E]));
vm_pcnext(); vm_pcnext();

View File

@ -268,10 +268,13 @@ typedef struct JanetFuncEnv JanetFuncEnv;
typedef struct JanetKV JanetKV; typedef struct JanetKV JanetKV;
typedef struct JanetStackFrame JanetStackFrame; typedef struct JanetStackFrame JanetStackFrame;
typedef struct JanetAbstractType JanetAbstractType; typedef struct JanetAbstractType JanetAbstractType;
typedef struct JanetArgs JanetArgs;
typedef struct JanetReg JanetReg; typedef struct JanetReg JanetReg;
typedef struct JanetSourceMapping JanetSourceMapping; typedef struct JanetSourceMapping JanetSourceMapping;
typedef int (*JanetCFunction)(JanetArgs args); typedef struct JanetView JanetView;
typedef struct JanetByteView JanetByteView;
typedef struct JanetDictView JanetDictView;
typedef struct JanetRange JanetRange;
typedef Janet (*JanetCFunction)(int32_t argc, Janet *argv);
/* Basic types for all Janet Values */ /* Basic types for all Janet Values */
typedef enum JanetType { typedef enum JanetType {
@ -573,13 +576,6 @@ JANET_API int janet_checkint64(Janet x);
#define janet_checktypes(x, tps) ((1 << janet_type(x)) & (tps)) #define janet_checktypes(x, tps) ((1 << janet_type(x)) & (tps))
/* Hold components of arguments passed to JanetCFunction. */
struct JanetArgs {
Janet *v;
Janet *ret;
int32_t n;
};
/* Fiber signal masks. */ /* Fiber signal masks. */
#define JANET_FIBER_MASK_ERROR 2 #define JANET_FIBER_MASK_ERROR 2
#define JANET_FIBER_MASK_DEBUG 4 #define JANET_FIBER_MASK_DEBUG 4
@ -760,6 +756,27 @@ struct JanetReg {
const char *documentation; const char *documentation;
}; };
struct JanetView {
const Janet *items;
int32_t len;
};
struct JanetByteView {
const uint8_t *bytes;
int32_t len;
};
struct JanetDictView {
const JanetKV *kvs;
int32_t len;
int32_t cap;
};
struct JanetRange {
int32_t start;
int32_t end;
};
/***** END SECTION TYPES *****/ /***** END SECTION TYPES *****/
/***** START SECTION OPCODES *****/ /***** START SECTION OPCODES *****/
@ -926,9 +943,9 @@ JANET_API int janet_dostring(JanetTable *env, const char *str, const char *sourc
JANET_API int janet_scan_number(const uint8_t *str, int32_t len, double *out); JANET_API int janet_scan_number(const uint8_t *str, int32_t len, double *out);
/* Debugging */ /* Debugging */
JANET_API int janet_debug_break(JanetFuncDef *def, int32_t pc); JANET_API void janet_debug_break(JanetFuncDef *def, int32_t pc);
JANET_API int janet_debug_unbreak(JanetFuncDef *def, int32_t pc); JANET_API void janet_debug_unbreak(JanetFuncDef *def, int32_t pc);
JANET_API int janet_debug_find( JANET_API void janet_debug_find(
JanetFuncDef **def_out, int32_t *pc_out, JanetFuncDef **def_out, int32_t *pc_out,
const uint8_t *source, int32_t offset); const uint8_t *source, int32_t offset);
@ -949,14 +966,14 @@ JANET_API JanetBuffer *janet_buffer_init(JanetBuffer *buffer, int32_t capacity);
JANET_API void janet_buffer_deinit(JanetBuffer *buffer); JANET_API void janet_buffer_deinit(JanetBuffer *buffer);
JANET_API void janet_buffer_ensure(JanetBuffer *buffer, int32_t capacity, int32_t growth); JANET_API void janet_buffer_ensure(JanetBuffer *buffer, int32_t capacity, int32_t growth);
JANET_API void janet_buffer_setcount(JanetBuffer *buffer, int32_t count); JANET_API void janet_buffer_setcount(JanetBuffer *buffer, int32_t count);
JANET_API int janet_buffer_extra(JanetBuffer *buffer, int32_t n); JANET_API void janet_buffer_extra(JanetBuffer *buffer, int32_t n);
JANET_API int janet_buffer_push_bytes(JanetBuffer *buffer, const uint8_t *string, int32_t len); JANET_API void janet_buffer_push_bytes(JanetBuffer *buffer, const uint8_t *string, int32_t len);
JANET_API int janet_buffer_push_string(JanetBuffer *buffer, const uint8_t *string); JANET_API void janet_buffer_push_string(JanetBuffer *buffer, const uint8_t *string);
JANET_API int janet_buffer_push_cstring(JanetBuffer *buffer, const char *cstring); JANET_API void janet_buffer_push_cstring(JanetBuffer *buffer, const char *cstring);
JANET_API int janet_buffer_push_u8(JanetBuffer *buffer, uint8_t x); JANET_API void janet_buffer_push_u8(JanetBuffer *buffer, uint8_t x);
JANET_API int janet_buffer_push_u16(JanetBuffer *buffer, uint16_t x); JANET_API void janet_buffer_push_u16(JanetBuffer *buffer, uint16_t x);
JANET_API int janet_buffer_push_u32(JanetBuffer *buffer, uint32_t x); JANET_API void janet_buffer_push_u32(JanetBuffer *buffer, uint32_t x);
JANET_API int janet_buffer_push_u64(JanetBuffer *buffer, uint64_t x); JANET_API void janet_buffer_push_u64(JanetBuffer *buffer, uint64_t x);
/* Tuple */ /* Tuple */
#define janet_tuple_raw(t) ((int32_t *)(t) - 4) #define janet_tuple_raw(t) ((int32_t *)(t) - 4)
@ -1054,7 +1071,8 @@ JANET_API const JanetKV *janet_dictionary_next(const JanetKV *kvs, int32_t cap,
JANET_API void *janet_abstract(const JanetAbstractType *type, size_t size); JANET_API void *janet_abstract(const JanetAbstractType *type, size_t size);
/* Native */ /* Native */
JANET_API JanetCFunction janet_native(const char *name, const uint8_t **error); typedef void (*JanetModule)(JanetTable *);
JANET_API JanetModule janet_native(const char *name, const uint8_t **error);
/* Marshaling */ /* Marshaling */
JANET_API int janet_marshal( JANET_API int janet_marshal(
@ -1119,160 +1137,44 @@ JANET_API void janet_def(JanetTable *env, const char *name, Janet val, const cha
JANET_API void janet_var(JanetTable *env, const char *name, Janet val, const char *documentation); JANET_API void janet_var(JanetTable *env, const char *name, Janet val, const char *documentation);
JANET_API void janet_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cfuns); JANET_API void janet_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cfuns);
JANET_API JanetBindingType janet_resolve(JanetTable *env, const uint8_t *sym, Janet *out); JANET_API JanetBindingType janet_resolve(JanetTable *env, const uint8_t *sym, Janet *out);
JANET_API JanetTable *janet_env(JanetArgs args);
JANET_API void janet_register(const char *name, JanetCFunction cfun); JANET_API void janet_register(const char *name, JanetCFunction cfun);
/* C Function helpers */
JANET_API int janet_arity_err(JanetArgs args, int32_t n, const char *prefix);
JANET_API int janet_type_err(JanetArgs args, int32_t n, JanetType expected);
JANET_API int janet_typemany_err(JanetArgs args, int32_t n, int expected);
JANET_API int janet_typeabstract_err(JanetArgs args, int32_t n, const JanetAbstractType *at);
/* New C API */ /* New C API */
#define JANET_MODULE_ENTRY JANET_API void _janet_init
JANET_API void janet_panicv(Janet message); JANET_API void janet_panicv(Janet message);
JANET_API void janet_panic(const char *message); JANET_API void janet_panic(const char *message);
JANET_API void janet_panics(const uint8_t *message); JANET_API void janet_panics(const uint8_t *message);
#define janet_panicf(...) janet_panics(janet_formatc(__VA_ARGS__)) #define janet_panicf(...) janet_panics(janet_formatc(__VA_ARGS__))
#define janet_printf(...) fputs((const char *)janet_formatc(__VA_ARGS__), stdout)
JANET_API void janet_panic_type(Janet x, int32_t n, int expected); JANET_API void janet_panic_type(Janet x, int32_t n, int expected);
JANET_API void janet_panic_abstract(Janet x, int32_t n, const JanetAbstractType *at);
JANET_API void janet_arity(int32_t arity, int32_t min, int32_t max);
/* Helpers for writing modules */ JANET_API double janet_getnumber(const Janet *argv, int32_t n);
#define JANET_MODULE_ENTRY JANET_API int _janet_init JANET_API JanetArray *janet_getarray(const Janet *argv, int32_t n);
JANET_API const Janet *janet_gettuple(const Janet *argv, int32_t n);
JANET_API JanetTable *janet_gettable(const Janet *argv, int32_t n);
JANET_API const JanetKV *janet_getstruct(const Janet *argv, int32_t n);
JANET_API const uint8_t *janet_getstring(const Janet *argv, int32_t n);
JANET_API const uint8_t *janet_getsymbol(const Janet *argv, int32_t n);
JANET_API const uint8_t *janet_getkeyword(const Janet *argv, int32_t n);
JANET_API JanetBuffer *janet_getbuffer(const Janet *argv, int32_t n);
JANET_API JanetFiber *janet_getfiber(const Janet *argv, int32_t n);
JANET_API JanetFunction *janet_getfunction(const Janet *argv, int32_t n);
JANET_API JanetCFunction janet_getcfunction(const Janet *argv, int32_t n);
JANET_API int janet_getboolean(const Janet *argv, int32_t n);
JANET_API int32_t janet_getinteger(const Janet *argv, int32_t n);
JANET_API int64_t janet_getinteger64(const Janet *argv, int32_t n);
JANET_API JanetView janet_getindexed(const Janet *argv, int32_t n);
JANET_API JanetByteView janet_getbytes(const Janet *argv, int32_t n);
JANET_API JanetDictView janet_getdictionary(const Janet *argv, int32_t n);
JANET_API void *janet_getabstract(const Janet *argv, int32_t n, const JanetAbstractType *at);
JANET_API JanetRange janet_getslice(int32_t argc, const Janet *argv);
/***** END SECTION MAIN *****/ /***** END SECTION MAIN *****/
/***** START SECTION MACROS *****/
/* Macros */
#define JANET_THROW(a, e) return (*((a).ret) = janet_cstringv(e), 1)
#define JANET_THROWV(a, v) return (*((a).ret) = (v), 1)
#define JANET_RETURN(a, v) return (*((a).ret) = (v), 0)
/* Early exit macros */
#define JANET_MAXARITY(A, N) do { if ((A).n > (N))\
return janet_arity_err(A, N, "at most "); } while (0)
#define JANET_MINARITY(A, N) do { if ((A).n < (N))\
return janet_arity_err(A, N, "at least "); } while (0)
#define JANET_FIXARITY(A, N) do { if ((A).n != (N))\
return janet_arity_err(A, N, ""); } while (0)
#define JANET_CHECK(A, N, T) do {\
if ((A).n > (N)) {\
if (!janet_checktype((A).v[(N)], (T))) return janet_type_err(A, N, T);\
} else {\
if ((T) != JANET_NIL) return janet_type_err(A, N, T);\
}\
} while (0)
#define JANET_CHECKMANY(A, N, TS) do {\
if ((A).n > (N)) {\
JanetType _t_ = janet_type((A).v[(N)]);\
if (!((1 << _t_) & (TS))) return janet_typemany_err(A, N, TS);\
} else {\
if (!((TS) & JANET_NIL)) return janet_typemany_err(A, N, TS);\
}\
} while (0)
#define JANET_CHECKABSTRACT(A, N, AT) do {\
if ((A).n > (N)) {\
Janet _x_ = (A).v[(N)];\
if (!janet_checktype(_x_, JANET_ABSTRACT) ||\
janet_abstract_type(janet_unwrap_abstract(_x_)) != (AT))\
return janet_typeabstract_err(A, N, AT);\
} else {\
return janet_typeabstract_err(A, N, AT);\
}\
} while (0)
#define JANET_ARG_BOOLEAN(DEST, A, N) do { \
JANET_CHECKMANY(A, N, JANET_TFLAG_TRUE | JANET_TFLAG_FALSE);\
DEST = janet_unwrap_boolean((A).v[(N)]); \
} while (0)
#define JANET_ARG_BYTES(DESTBYTES, DESTLEN, A, N) do {\
if ((A).n <= (N)) return janet_typemany_err(A, N, JANET_TFLAG_BYTES);\
if (!janet_bytes_view((A).v[(N)], &(DESTBYTES), &(DESTLEN))) {\
return janet_typemany_err(A, N, JANET_TFLAG_BYTES);\
}\
} while (0)
#define JANET_ARG_INDEXED(DESTVALS, DESTLEN, A, N) do {\
if ((A).n <= (N)) return janet_typemany_err(A, N, JANET_TFLAG_INDEXED);\
if (!janet_indexed_view((A).v[(N)], &(DESTVALS), &(DESTLEN))) {\
return janet_typemany_err(A, N, JANET_TFLAG_INDEXED);\
}\
} while (0)
#define _JANET_ARG(TYPE, NAME, DEST, A, N) do { \
JANET_CHECK(A, N, TYPE);\
DEST = janet_unwrap_##NAME((A).v[(N)]); \
} while (0)
#define JANET_ARG_FIBER(DEST, A, N) _JANET_ARG(JANET_FIBER, fiber, DEST, A, N)
#define JANET_ARG_NUMBER(DEST, A, N) _JANET_ARG(JANET_NUMBER, number, DEST, A, N)
#define JANET_ARG_STRING(DEST, A, N) _JANET_ARG(JANET_STRING, string, DEST, A, N)
#define JANET_ARG_SYMBOL(DEST, A, N) _JANET_ARG(JANET_SYMBOL, symbol, DEST, A, N)
#define JANET_ARG_KEYWORD(DEST, A, N) _JANET_ARG(JANET_KEYWORD, keyword, DEST, A, N)
#define JANET_ARG_ARRAY(DEST, A, N) _JANET_ARG(JANET_ARRAY, array, DEST, A, N)
#define JANET_ARG_TUPLE(DEST, A, N) _JANET_ARG(JANET_TUPLE, tuple, DEST, A, N)
#define JANET_ARG_TABLE(DEST, A, N) _JANET_ARG(JANET_TABLE, table, DEST, A, N)
#define JANET_ARG_STRUCT(DEST, A, N) _JANET_ARG(JANET_STRUCT, struct, DEST, A, N)
#define JANET_ARG_BUFFER(DEST, A, N) _JANET_ARG(JANET_BUFFER, buffer, DEST, A, N)
#define JANET_ARG_FUNCTION(DEST, A, N) _JANET_ARG(JANET_FUNCTION, function, DEST, A, N)
#define JANET_ARG_CFUNCTION(DEST, A, N) _JANET_ARG(JANET_CFUNCTION, cfunction, DEST, A, N)
#define JANET_ARG_INTEGER(DEST, A, N) do { \
if ((A).n <= (N) || !janet_checktype((A).v[(N)], JANET_NUMBER)) { \
JANET_THROW(A, "expected integer"); \
} \
double _x_ = janet_unwrap_number((A).v[(N)]); \
if (janet_checkintrange(_x_)) { \
DEST = (int32_t) _x_; \
} else { \
JANET_THROW(A, "expected integer representable by 32 bits"); \
} \
} while (0)
#define JANET_ARG_INTEGER64(DEST, A, N) do { \
if ((A).n <= (N) || !janet_checktype((A).v[(N)], JANET_NUMBER)) { \
JANET_THROW(A, "expected integer"); \
} \
double _x_ = janet_unwrap_number((A).v[(N)]); \
if (janet_checkintrange64(_x_)) { \
DEST = (int64_t) _x_; \
} else { \
JANET_THROW(A, "expected integer representable by 64 bits"); \
} \
} while (0)
#define JANET_ARG_ABSTRACT(DEST, A, N, AT) do { \
JANET_CHECKABSTRACT(A, N, AT); \
DEST = janet_unwrap_abstract((A).v[(N)]); \
} while (0)
#define JANET_RETURN_NIL(A) do { return JANET_SIGNAL_OK; } while (0)
#define JANET_RETURN_FALSE(A) JANET_RETURN(A, janet_wrap_false())
#define JANET_RETURN_TRUE(A) JANET_RETURN(A, janet_wrap_true())
#define JANET_RETURN_BOOLEAN(A, X) JANET_RETURN(A, janet_wrap_boolean(X))
#define JANET_RETURN_FIBER(A, X) JANET_RETURN(A, janet_wrap_fiber(X))
#define JANET_RETURN_NUMBER(A, X) JANET_RETURN(A, janet_wrap_number(X))
#define JANET_RETURN_STRING(A, X) JANET_RETURN(A, janet_wrap_string(X))
#define JANET_RETURN_SYMBOL(A, X) JANET_RETURN(A, janet_wrap_symbol(X))
#define JANET_RETURN_KEYWORD(A, X) JANET_RETURN(A, janet_wrap_keyword(X))
#define JANET_RETURN_ARRAY(A, X) JANET_RETURN(A, janet_wrap_array(X))
#define JANET_RETURN_TUPLE(A, X) JANET_RETURN(A, janet_wrap_tuple(X))
#define JANET_RETURN_TABLE(A, X) JANET_RETURN(A, janet_wrap_table(X))
#define JANET_RETURN_STRUCT(A, X) JANET_RETURN(A, janet_wrap_struct(X))
#define JANET_RETURN_BUFFER(A, X) JANET_RETURN(A, janet_wrap_buffer(X))
#define JANET_RETURN_FUNCTION(A, X) JANET_RETURN(A, janet_wrap_function(X))
#define JANET_RETURN_CFUNCTION(A, X) JANET_RETURN(A, janet_wrap_cfunction(X))
#define JANET_RETURN_ABSTRACT(A, X) JANET_RETURN(A, janet_wrap_abstract(X))
#define JANET_RETURN_CSTRING(A, X) JANET_RETURN(A, janet_cstringv(X))
#define JANET_RETURN_CSYMBOL(A, X) JANET_RETURN(A, janet_csymbolv(X))
#define JANET_RETURN_CKEYWORD(A, X) JANET_RETURN(A, janet_ckeywordv(X))
#define JANET_RETURN_INTEGER(A, X) JANET_RETURN(A, janet_wrap_number((double) (X)))
/**** END SECTION MACROS *****/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -23,14 +23,12 @@
#include "line.h" #include "line.h"
/* Common */ /* Common */
int janet_line_getter(JanetArgs args) { Janet janet_line_getter(int32_t argc, Janet *argv) {
JANET_FIXARITY(args, 2); janet_arity(argc, 2, 2);
JANET_CHECK(args, 0, JANET_STRING); const uint8_t *str = janet_getstring(argv, 0);
JANET_CHECK(args, 1, JANET_BUFFER); JanetBuffer *buf = janet_getbuffer(argv, 1);
janet_line_get( janet_line_get(str, buf);
janet_unwrap_string(args.v[0]), return argv[0];
janet_unwrap_buffer(args.v[1]));
JANET_RETURN(args, args.v[0]);
} }
static void simpleline(JanetBuffer *buffer) { static void simpleline(JanetBuffer *buffer) {

View File

@ -29,6 +29,6 @@ void janet_line_init();
void janet_line_deinit(); void janet_line_deinit();
void janet_line_get(const uint8_t *p, JanetBuffer *buffer); void janet_line_get(const uint8_t *p, JanetBuffer *buffer);
int janet_line_getter(JanetArgs args); Janet janet_line_getter(int32_t argc, Janet *argv);
#endif #endif