mirror of
https://github.com/janet-lang/janet
synced 2024-11-28 11:09:54 +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:
parent
5b62c8e6db
commit
b60e3e302a
146
src/core/array.c
146
src/core/array.c
@ -118,135 +118,97 @@ Janet janet_array_peek(JanetArray *array) {
|
||||
|
||||
/* C Functions */
|
||||
|
||||
static int cfun_new(JanetArgs args) {
|
||||
int32_t cap;
|
||||
JanetArray *array;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_INTEGER(cap, args, 0);
|
||||
array = janet_array(cap);
|
||||
JANET_RETURN_ARRAY(args, array);
|
||||
static Janet cfun_new(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
int32_t cap = janet_getinteger(argv, 0);
|
||||
JanetArray *array = janet_array(cap);
|
||||
return janet_wrap_array(array);
|
||||
}
|
||||
|
||||
static int cfun_pop(JanetArgs args) {
|
||||
JanetArray *array;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_ARRAY(array, args, 0);
|
||||
JANET_RETURN(args, janet_array_pop(array));
|
||||
static Janet cfun_pop(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetArray *array = janet_getarray(argv, 0);
|
||||
return janet_array_pop(array);
|
||||
}
|
||||
|
||||
static int cfun_peek(JanetArgs args) {
|
||||
JanetArray *array;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_ARRAY(array, args, 0);
|
||||
JANET_RETURN(args, janet_array_peek(array));
|
||||
static Janet cfun_peek(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetArray *array = janet_getarray(argv, 0);
|
||||
return janet_array_peek(array);
|
||||
}
|
||||
|
||||
static int cfun_push(JanetArgs args) {
|
||||
JanetArray *array;
|
||||
int32_t newcount;
|
||||
JANET_MINARITY(args, 1);
|
||||
JANET_ARG_ARRAY(array, args, 0);
|
||||
newcount = array->count - 1 + args.n;
|
||||
static Janet cfun_push(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, -1);
|
||||
JanetArray *array = janet_getarray(argv, 0);
|
||||
int32_t newcount = array->count - 1 + argc;
|
||||
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;
|
||||
JANET_RETURN(args, args.v[0]);
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static int cfun_ensure(JanetArgs args) {
|
||||
JanetArray *array;
|
||||
int32_t newcount;
|
||||
int32_t growth;
|
||||
JANET_FIXARITY(args, 3);
|
||||
JANET_ARG_ARRAY(array, args, 0);
|
||||
JANET_ARG_INTEGER(newcount, args, 1);
|
||||
JANET_ARG_INTEGER(growth, args, 2);
|
||||
if (newcount < 0) JANET_THROW(args, "expected positive integer");
|
||||
static Janet cfun_ensure(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 3, 3);
|
||||
JanetArray *array = janet_getarray(argv, 0);
|
||||
int32_t newcount = janet_getinteger(argv, 1);
|
||||
int32_t growth = janet_getinteger(argv, 2);
|
||||
if (newcount < 1) janet_panic("expected positive integer");
|
||||
janet_array_ensure(array, newcount, growth);
|
||||
JANET_RETURN(args, args.v[0]);
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static int cfun_slice(JanetArgs args) {
|
||||
const Janet *vals;
|
||||
int32_t len;
|
||||
JanetArray *ret;
|
||||
int32_t start, end;
|
||||
JANET_MINARITY(args, 1);
|
||||
JANET_MAXARITY(args, 3);
|
||||
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 Janet cfun_slice(int32_t argc, Janet *argv) {
|
||||
JanetRange range = janet_getslice(argc, argv);
|
||||
JanetView view = janet_getindexed(argv, 0);
|
||||
JanetArray *array = janet_array(range.end - range.start);
|
||||
memcpy(array->data, view.items + range.start, sizeof(Janet) * (range.end - range.start));
|
||||
array->count = range.end - range.start;
|
||||
return janet_wrap_array(array);
|
||||
}
|
||||
|
||||
static int cfun_concat(JanetArgs args) {
|
||||
static Janet cfun_concat(int32_t argc, Janet *argv) {
|
||||
int32_t i;
|
||||
JanetArray *array;
|
||||
JANET_MINARITY(args, 1);
|
||||
JANET_ARG_ARRAY(array, args, 0);
|
||||
for (i = 1; i < args.n; i++) {
|
||||
switch (janet_type(args.v[i])) {
|
||||
janet_arity(argc, 1, -1);
|
||||
JanetArray *array = janet_getarray(argv, 0);
|
||||
for (i = 1; i < argc; i++) {
|
||||
switch (janet_type(argv[i])) {
|
||||
default:
|
||||
janet_array_push(array, args.v[i]);
|
||||
janet_array_push(array, argv[i]);
|
||||
break;
|
||||
case JANET_ARRAY:
|
||||
case JANET_TUPLE:
|
||||
{
|
||||
int32_t j, len;
|
||||
const Janet *vals;
|
||||
janet_indexed_view(args.v[i], &vals, &len);
|
||||
janet_indexed_view(argv[i], &vals, &len);
|
||||
for (j = 0; j < len; j++)
|
||||
janet_array_push(array, vals[j]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
JANET_RETURN_ARRAY(args, array);
|
||||
return janet_wrap_array(array);
|
||||
}
|
||||
|
||||
static int cfun_insert(JanetArgs args) {
|
||||
int32_t at;
|
||||
static Janet cfun_insert(int32_t argc, Janet *argv) {
|
||||
size_t chunksize, restsize;
|
||||
JanetArray *array;
|
||||
JANET_MINARITY(args, 2);
|
||||
JANET_ARG_ARRAY(array, args, 0);
|
||||
JANET_ARG_INTEGER(at, args, 1);
|
||||
janet_arity(argc, 2, -1);
|
||||
JanetArray *array = janet_getarray(argv, 0);
|
||||
int32_t at = janet_getinteger(argv, 1);
|
||||
if (at < 0) {
|
||||
at = array->count + at + 1;
|
||||
}
|
||||
if (at < 0 || at > array->count)
|
||||
JANET_THROW(args, "insertion index out of bounds");
|
||||
chunksize = (args.n - 2) * sizeof(Janet);
|
||||
janet_panicf("insertion index %d out of range [0,%d]", at, array->count);
|
||||
chunksize = (argc - 2) * sizeof(Janet);
|
||||
restsize = (array->count - at) * sizeof(Janet);
|
||||
janet_array_ensure(array, array->count + args.n - 2, 2);
|
||||
memmove(array->data + at + args.n - 2,
|
||||
janet_array_ensure(array, array->count + argc - 2, 2);
|
||||
memmove(array->data + at + argc - 2,
|
||||
array->data + at,
|
||||
restsize);
|
||||
memcpy(array->data + at, args.v + 2, chunksize);
|
||||
array->count += (args.n - 2);
|
||||
JANET_RETURN_ARRAY(args, array);
|
||||
memcpy(array->data + at, argv + 2, chunksize);
|
||||
array->count += (argc - 2);
|
||||
return janet_wrap_array(array);
|
||||
}
|
||||
|
||||
static const JanetReg cfuns[] = {
|
||||
@ -300,8 +262,6 @@ static const JanetReg cfuns[] = {
|
||||
};
|
||||
|
||||
/* Load the array module */
|
||||
int janet_lib_array(JanetArgs args) {
|
||||
JanetTable *env = janet_env(args);
|
||||
void janet_lib_array(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, cfuns);
|
||||
return 0;
|
||||
}
|
||||
|
@ -914,22 +914,20 @@ Janet janet_disasm(JanetFuncDef *def) {
|
||||
}
|
||||
|
||||
/* 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;
|
||||
JANET_FIXARITY(args, 1);
|
||||
res = janet_asm(args.v[0], 0);
|
||||
if (res.status == JANET_ASSEMBLE_OK) {
|
||||
JANET_RETURN_FUNCTION(args, janet_thunk(res.funcdef));
|
||||
} else {
|
||||
JANET_THROWV(args, janet_wrap_string(res.error));
|
||||
res = janet_asm(argv[0], 0);
|
||||
if (res.status != JANET_ASSEMBLE_OK) {
|
||||
janet_panics(res.error);
|
||||
}
|
||||
return janet_wrap_function(janet_thunk(res.funcdef));
|
||||
}
|
||||
|
||||
static int cfun_disasm(JanetArgs args) {
|
||||
JanetFunction *f;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_FUNCTION(f, args, 0);
|
||||
JANET_RETURN(args, janet_disasm(f->def));
|
||||
static Janet cfun_disasm(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetFunction *f = janet_getfunction(argv, 0);
|
||||
return janet_disasm(f->def);
|
||||
}
|
||||
|
||||
static const JanetReg cfuns[] = {
|
||||
@ -949,10 +947,8 @@ static const JanetReg cfuns[] = {
|
||||
};
|
||||
|
||||
/* Load the library */
|
||||
int janet_lib_asm(JanetArgs args) {
|
||||
JanetTable *env = janet_env(args);
|
||||
void janet_lib_asm(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, cfuns);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -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
|
||||
* 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 */
|
||||
if ((int64_t)n + buffer->count > INT32_MAX) {
|
||||
return -1;
|
||||
janet_panic("buffer overflow");
|
||||
}
|
||||
int32_t new_size = buffer->count + n;
|
||||
if (new_size > buffer->capacity) {
|
||||
@ -92,59 +92,54 @@ int janet_buffer_extra(JanetBuffer *buffer, int32_t n) {
|
||||
buffer->data = new_data;
|
||||
buffer->capacity = new_capacity;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
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 */
|
||||
int janet_buffer_push_bytes(JanetBuffer *buffer, const uint8_t *string, int32_t length) {
|
||||
if (janet_buffer_extra(buffer, length)) return -1;
|
||||
void janet_buffer_push_bytes(JanetBuffer *buffer, const uint8_t *string, int32_t length) {
|
||||
janet_buffer_extra(buffer, length);
|
||||
memcpy(buffer->data + buffer->count, string, length);
|
||||
buffer->count += length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int janet_buffer_push_string(JanetBuffer *buffer, const uint8_t *string) {
|
||||
return janet_buffer_push_bytes(buffer, string, janet_string_length(string));
|
||||
void janet_buffer_push_string(JanetBuffer *buffer, const uint8_t *string) {
|
||||
janet_buffer_push_bytes(buffer, string, janet_string_length(string));
|
||||
}
|
||||
|
||||
/* Push a single byte to the buffer */
|
||||
int janet_buffer_push_u8(JanetBuffer *buffer, uint8_t byte) {
|
||||
if (janet_buffer_extra(buffer, 1)) return -1;
|
||||
void janet_buffer_push_u8(JanetBuffer *buffer, uint8_t byte) {
|
||||
janet_buffer_extra(buffer, 1);
|
||||
buffer->data[buffer->count] = byte;
|
||||
buffer->count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Push a 16 bit unsigned integer to the buffer */
|
||||
int janet_buffer_push_u16(JanetBuffer *buffer, uint16_t x) {
|
||||
if (janet_buffer_extra(buffer, 2)) return -1;
|
||||
void janet_buffer_push_u16(JanetBuffer *buffer, uint16_t x) {
|
||||
janet_buffer_extra(buffer, 2);
|
||||
buffer->data[buffer->count] = x & 0xFF;
|
||||
buffer->data[buffer->count + 1] = (x >> 8) & 0xFF;
|
||||
buffer->count += 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Push a 32 bit unsigned integer to the buffer */
|
||||
int janet_buffer_push_u32(JanetBuffer *buffer, uint32_t x) {
|
||||
if (janet_buffer_extra(buffer, 4)) return -1;
|
||||
void janet_buffer_push_u32(JanetBuffer *buffer, uint32_t x) {
|
||||
janet_buffer_extra(buffer, 4);
|
||||
buffer->data[buffer->count] = x & 0xFF;
|
||||
buffer->data[buffer->count + 1] = (x >> 8) & 0xFF;
|
||||
buffer->data[buffer->count + 2] = (x >> 16) & 0xFF;
|
||||
buffer->data[buffer->count + 3] = (x >> 24) & 0xFF;
|
||||
buffer->count += 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Push a 64 bit unsigned integer to the buffer */
|
||||
int janet_buffer_push_u64(JanetBuffer *buffer, uint64_t x) {
|
||||
if (janet_buffer_extra(buffer, 8)) return -1;
|
||||
void janet_buffer_push_u64(JanetBuffer *buffer, uint64_t x) {
|
||||
janet_buffer_extra(buffer, 8);
|
||||
buffer->data[buffer->count] = x & 0xFF;
|
||||
buffer->data[buffer->count + 1] = (x >> 8) & 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 + 7] = (x >> 56) & 0xFF;
|
||||
buffer->count += 8;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* C functions */
|
||||
|
||||
static int cfun_new(JanetArgs args) {
|
||||
int32_t cap;
|
||||
JanetBuffer *buffer;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_INTEGER(cap, args, 0);
|
||||
buffer = janet_buffer(cap);
|
||||
JANET_RETURN_BUFFER(args, buffer);
|
||||
static Janet cfun_new(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
int32_t cap = janet_getinteger(argv, 0);
|
||||
JanetBuffer *buffer = janet_buffer(cap);
|
||||
return janet_wrap_buffer(buffer);
|
||||
}
|
||||
|
||||
static int cfun_u8(JanetArgs args) {
|
||||
static Janet cfun_u8(int32_t argc, Janet *argv) {
|
||||
int32_t i;
|
||||
JanetBuffer *buffer;
|
||||
JANET_MINARITY(args, 1);
|
||||
JANET_ARG_BUFFER(buffer, args, 0);
|
||||
for (i = 1; i < args.n; i++) {
|
||||
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_arity(argc, 1, -1);
|
||||
JanetBuffer *buffer = janet_getbuffer(argv, 0);
|
||||
for (i = 1; i < argc; i++) {
|
||||
janet_buffer_push_u8(buffer, (uint8_t) (janet_getinteger(argv, i) & 0xFF));
|
||||
}
|
||||
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;
|
||||
JanetBuffer *buffer;
|
||||
JANET_MINARITY(args, 1);
|
||||
JANET_ARG_BUFFER(buffer, args, 0);
|
||||
for (i = 1; i < args.n; i++) {
|
||||
double number;
|
||||
uint32_t word;
|
||||
JANET_ARG_NUMBER(number, args, i);
|
||||
word = (uint32_t) number;
|
||||
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_arity(argc, 1, -1);
|
||||
JanetBuffer *buffer = janet_getbuffer(argv, 0);
|
||||
for (i = 1; i < argc; i++) {
|
||||
double number = janet_getnumber(argv, 0);
|
||||
uint32_t word = (uint32_t) number;
|
||||
if (word != number)
|
||||
janet_panicf("cannot convert %v to machine word", argv[0]);
|
||||
janet_buffer_push_u32(buffer, word);
|
||||
}
|
||||
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;
|
||||
JanetBuffer *buffer;
|
||||
JANET_MINARITY(args, 1);
|
||||
JANET_ARG_BUFFER(buffer, args, 0);
|
||||
for (i = 1; i < args.n; i++) {
|
||||
int32_t 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_arity(argc, 1, -1);
|
||||
JanetBuffer *buffer = janet_getbuffer(argv, 0);
|
||||
for (i = 1; i < argc; i++) {
|
||||
JanetByteView view = janet_getbytes(argv, i);
|
||||
janet_buffer_push_bytes(buffer, view.bytes, view.len);
|
||||
}
|
||||
JANET_RETURN(args, args.v[0]);
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static int cfun_clear(JanetArgs args) {
|
||||
JanetBuffer *buffer;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_BUFFER(buffer, args, 0);
|
||||
static Janet cfun_clear(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetBuffer *buffer = janet_getbuffer(argv, 0);
|
||||
buffer->count = 0;
|
||||
JANET_RETURN(args, args.v[0]);
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static int cfun_popn(JanetArgs args) {
|
||||
JanetBuffer *buffer;
|
||||
int32_t n;
|
||||
JANET_FIXARITY(args, 2);
|
||||
JANET_ARG_BUFFER(buffer, args, 0);
|
||||
JANET_ARG_INTEGER(n, args, 1);
|
||||
if (n < 0) JANET_THROW(args, "n must be non-negative");
|
||||
static Janet cfun_popn(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 2, 2);
|
||||
JanetBuffer *buffer = janet_getbuffer(argv, 0);
|
||||
int32_t n = janet_getinteger(argv, 1);
|
||||
if (n < 0) janet_panic("n must be non-negative");
|
||||
if (buffer->count < n) {
|
||||
buffer->count = 0;
|
||||
} else {
|
||||
buffer->count -= n;
|
||||
}
|
||||
JANET_RETURN(args, args.v[0]);
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static int cfun_slice(JanetArgs args) {
|
||||
const uint8_t *data;
|
||||
int32_t len, start, end;
|
||||
JanetBuffer *ret;
|
||||
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_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 Janet cfun_slice(int32_t argc, Janet *argv) {
|
||||
JanetRange range = janet_getslice(argc, argv);
|
||||
JanetByteView view = janet_getbytes(argv, 0);
|
||||
JanetBuffer *buffer = janet_buffer(range.end - range.start);
|
||||
memcpy(buffer->data, view.bytes + range.start, range.end - range.start);
|
||||
buffer->count = range.end - range.start;
|
||||
return janet_wrap_buffer(buffer);
|
||||
}
|
||||
|
||||
static const JanetReg cfuns[] = {
|
||||
@ -310,8 +266,6 @@ static const JanetReg cfuns[] = {
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
int janet_lib_buffer(JanetArgs args) {
|
||||
JanetTable *env = janet_env(args);
|
||||
void janet_lib_buffer(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, cfuns);
|
||||
return 0;
|
||||
}
|
||||
|
138
src/core/capi.c
138
src/core/capi.c
@ -43,5 +43,141 @@ void janet_panics(const uint8_t *message) {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -699,29 +699,25 @@ JanetCompileResult janet_compile(Janet source, JanetTable *env, const uint8_t *w
|
||||
}
|
||||
|
||||
/* C Function for compiling */
|
||||
static int cfun(JanetArgs args) {
|
||||
JanetCompileResult res;
|
||||
JanetTable *t;
|
||||
JanetTable *env;
|
||||
JANET_MINARITY(args, 2);
|
||||
JANET_MAXARITY(args, 3);
|
||||
JANET_ARG_TABLE(env, args, 1);
|
||||
static Janet cfun(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 2, 3);
|
||||
JanetTable *env = janet_gettable(argv, 1);
|
||||
const uint8_t *source = NULL;
|
||||
if (args.n == 3) {
|
||||
JANET_ARG_STRING(source, args, 2);
|
||||
if (argc == 3) {
|
||||
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) {
|
||||
JANET_RETURN_FUNCTION(args, janet_thunk(res.funcdef));
|
||||
return janet_wrap_function(janet_thunk(res.funcdef));
|
||||
} 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("start"), janet_wrap_integer(res.error_mapping.start));
|
||||
janet_table_put(t, janet_ckeywordv("end"), janet_wrap_integer(res.error_mapping.end));
|
||||
if (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}
|
||||
};
|
||||
|
||||
int janet_lib_compile(JanetArgs args) {
|
||||
JanetTable *env = janet_env(args);
|
||||
void janet_lib_compile(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, cfuns);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1451,7 +1451,7 @@ value, one key will be ignored."
|
||||
env)
|
||||
|
||||
(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."
|
||||
[sig x f source]
|
||||
(def title
|
||||
|
@ -50,14 +50,14 @@ typedef void *Clib;
|
||||
#define error_clib() dlerror()
|
||||
#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);
|
||||
JanetCFunction init;
|
||||
JanetModule init;
|
||||
if (!lib) {
|
||||
*error = janet_cstring(error_clib());
|
||||
return NULL;
|
||||
}
|
||||
init = (JanetCFunction) symbol_clib(lib, "_janet_init");
|
||||
init = (JanetModule) symbol_clib(lib, "_janet_init");
|
||||
if (!init) {
|
||||
*error = janet_cstring("could not find _janet_init symbol");
|
||||
return NULL;
|
||||
@ -65,217 +65,205 @@ JanetCFunction janet_native(const char *name, const uint8_t **error) {
|
||||
return init;
|
||||
}
|
||||
|
||||
static int janet_core_native(JanetArgs args) {
|
||||
JanetCFunction init;
|
||||
static Janet janet_core_native(int32_t argc, Janet *argv) {
|
||||
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 *path = NULL;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_STRING(path, args, 0);
|
||||
init = janet_native((const char *)path, &error);
|
||||
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) {
|
||||
int32_t i;
|
||||
for (i = 0; i < args.n; ++i) {
|
||||
static Janet janet_core_print(int32_t argc, Janet *argv) {
|
||||
for (int32_t i = 0; i < argc; ++i) {
|
||||
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);
|
||||
for (j = 0; j < len; ++j) {
|
||||
putc(vstr[j], stdout);
|
||||
}
|
||||
}
|
||||
putc('\n', stdout);
|
||||
JANET_RETURN_NIL(args);
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
static int janet_core_describe(JanetArgs args) {
|
||||
int32_t i;
|
||||
static Janet janet_core_describe(int32_t argc, Janet *argv) {
|
||||
JanetBuffer b;
|
||||
janet_buffer_init(&b, 0);
|
||||
for (i = 0; i < args.n; ++i) {
|
||||
for (int32_t i = 0; i < argc; ++i) {
|
||||
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);
|
||||
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);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int janet_core_string(JanetArgs args) {
|
||||
int32_t i;
|
||||
static Janet janet_core_string(int32_t argc, Janet *argv) {
|
||||
JanetBuffer b;
|
||||
janet_buffer_init(&b, 0);
|
||||
for (i = 0; i < args.n; ++i) {
|
||||
for (int32_t i = 0; i < argc; ++i) {
|
||||
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);
|
||||
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);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int janet_core_symbol(JanetArgs args) {
|
||||
static Janet janet_core_symbol(int32_t argc, Janet *argv) {
|
||||
int32_t i;
|
||||
JanetBuffer b;
|
||||
janet_buffer_init(&b, 0);
|
||||
for (i = 0; i < args.n; ++i) {
|
||||
for (i = 0; i < argc; ++i) {
|
||||
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);
|
||||
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);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int janet_core_keyword(JanetArgs args) {
|
||||
static Janet janet_core_keyword(int32_t argc, Janet *argv) {
|
||||
int32_t i;
|
||||
JanetBuffer b;
|
||||
janet_buffer_init(&b, 0);
|
||||
for (i = 0; i < args.n; ++i) {
|
||||
for (i = 0; i < argc; ++i) {
|
||||
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);
|
||||
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);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int janet_core_buffer(JanetArgs args) {
|
||||
static Janet janet_core_buffer(int32_t argc, Janet *argv) {
|
||||
int32_t i;
|
||||
JanetBuffer *b = janet_buffer(0);
|
||||
for (i = 0; i < args.n; ++i) {
|
||||
for (i = 0; i < argc; ++i) {
|
||||
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);
|
||||
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) {
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_RETURN_BOOLEAN(args, janet_checktype(args.v[0], JANET_ABSTRACT));
|
||||
static Janet janet_core_is_abstract(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
return janet_wrap_boolean(janet_checktype(argv[0], JANET_ABSTRACT));
|
||||
}
|
||||
|
||||
static int janet_core_scannumber(JanetArgs args) {
|
||||
const uint8_t *data;
|
||||
double val;
|
||||
int32_t len;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_BYTES(data, len, args, 0);
|
||||
if (janet_scan_number(data, len, &val))
|
||||
JANET_THROW(args, "failed to scan number");
|
||||
JANET_RETURN_NUMBER(args, val);
|
||||
static Janet janet_core_scannumber(int32_t argc, Janet *argv) {
|
||||
double number;
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetByteView view = janet_getbytes(argv, 1);
|
||||
if (janet_scan_number(view.bytes, view.len, &number))
|
||||
return janet_wrap_nil();
|
||||
return janet_wrap_number(number);
|
||||
}
|
||||
|
||||
static int janet_core_tuple(JanetArgs args) {
|
||||
JANET_RETURN_TUPLE(args, janet_tuple_n(args.v, args.n));
|
||||
static Janet janet_core_tuple(int32_t argc, Janet *argv) {
|
||||
return janet_wrap_tuple(janet_tuple_n(argv, argc));
|
||||
}
|
||||
|
||||
static int janet_core_array(JanetArgs args) {
|
||||
JanetArray *array = janet_array(args.n);
|
||||
array->count = args.n;
|
||||
memcpy(array->data, args.v, args.n * sizeof(Janet));
|
||||
JANET_RETURN_ARRAY(args, array);
|
||||
static Janet janet_core_array(int32_t argc, Janet *argv) {
|
||||
JanetArray *array = janet_array(argc);
|
||||
array->count = argc;
|
||||
memcpy(array->data, argv, argc * sizeof(Janet));
|
||||
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;
|
||||
JanetTable *table = janet_table(args.n >> 1);
|
||||
if (args.n & 1)
|
||||
JANET_THROW(args, "expected even number of arguments");
|
||||
for (i = 0; i < args.n; i += 2) {
|
||||
janet_table_put(table, args.v[i], args.v[i + 1]);
|
||||
if (argc & 1)
|
||||
janet_panic("expected even number of arguments");
|
||||
JanetTable *table = janet_table(argc >> 1);
|
||||
for (i = 0; i < argc; i += 2) {
|
||||
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;
|
||||
JanetKV *st = janet_struct_begin(args.n >> 1);
|
||||
if (args.n & 1)
|
||||
JANET_THROW(args, "expected even number of arguments");
|
||||
for (i = 0; i < args.n; i += 2) {
|
||||
janet_struct_put(st, args.v[i], args.v[i + 1]);
|
||||
if (argc & 1)
|
||||
janet_panic("expected even number of arguments");
|
||||
JanetKV *st = janet_struct_begin(argc >> 1);
|
||||
for (i = 0; i < argc; i += 2) {
|
||||
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) {
|
||||
JANET_FIXARITY(args, 0);
|
||||
JANET_RETURN_SYMBOL(args, janet_symbol_gen());
|
||||
static Janet janet_core_gensym(int32_t argc, Janet *argv) {
|
||||
(void) argv;
|
||||
janet_arity(argc, 0, 0);
|
||||
return janet_wrap_symbol(janet_symbol_gen());
|
||||
}
|
||||
|
||||
static int janet_core_gccollect(JanetArgs args) {
|
||||
(void) args;
|
||||
static Janet janet_core_gccollect(int32_t argc, Janet *argv) {
|
||||
(void) argv;
|
||||
(void) argc;
|
||||
janet_collect();
|
||||
return 0;
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
static int janet_core_gcsetinterval(JanetArgs args) {
|
||||
int32_t val;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_INTEGER(val, args, 0);
|
||||
static Janet janet_core_gcsetinterval(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
int32_t val = janet_getinteger(argv, 0);
|
||||
if (val < 0)
|
||||
JANET_THROW(args, "expected non-negative integer");
|
||||
janet_panic("expected non-negative integer");
|
||||
janet_vm_gc_interval = val;
|
||||
JANET_RETURN_NIL(args);
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
static int janet_core_gcinterval(JanetArgs args) {
|
||||
JANET_FIXARITY(args, 0);
|
||||
JANET_RETURN_INTEGER(args, janet_vm_gc_interval);
|
||||
static Janet janet_core_gcinterval(int32_t argc, Janet *argv) {
|
||||
(void) argv;
|
||||
janet_arity(argc, 0, 0);
|
||||
return janet_wrap_number(janet_vm_gc_interval);
|
||||
}
|
||||
|
||||
static int janet_core_type(JanetArgs args) {
|
||||
JANET_FIXARITY(args, 1);
|
||||
JanetType t = janet_type(args.v[0]);
|
||||
static Janet janet_core_type(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetType t = janet_type(argv[0]);
|
||||
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 {
|
||||
JANET_RETURN(args, janet_ckeywordv(janet_type_names[t]));
|
||||
return janet_ckeywordv(janet_type_names[t]);
|
||||
}
|
||||
}
|
||||
|
||||
static int janet_core_next(JanetArgs args) {
|
||||
Janet ds;
|
||||
const JanetKV *kv;
|
||||
JANET_FIXARITY(args, 2);
|
||||
JANET_CHECKMANY(args, 0, JANET_TFLAG_DICTIONARY);
|
||||
ds = args.v[0];
|
||||
if (janet_checktype(ds, JANET_TABLE)) {
|
||||
JanetTable *t = janet_unwrap_table(ds);
|
||||
kv = janet_checktype(args.v[1], JANET_NIL)
|
||||
? NULL
|
||||
: 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);
|
||||
static Janet janet_core_next(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 2, 2);
|
||||
JanetDictView view = janet_getdictionary(argv, 0);
|
||||
const JanetKV *end = view.kvs + view.cap;
|
||||
const JanetKV *kv = janet_checktype(argv[1], JANET_NIL)
|
||||
? view.kvs
|
||||
: janet_dict_find(view.kvs, view.cap, argv[1]) + 1;
|
||||
while (kv < end) {
|
||||
if (!janet_checktype(kv->key, JANET_NIL)) return kv->key;
|
||||
kv++;
|
||||
}
|
||||
if (kv)
|
||||
JANET_RETURN(args, kv->key);
|
||||
JANET_RETURN_NIL(args);
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
static int janet_core_hash(JanetArgs args) {
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_RETURN_INTEGER(args, janet_hash(args.v[0]));
|
||||
static Janet janet_core_hash(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
return janet_wrap_number(janet_hash(argv[0]));
|
||||
}
|
||||
|
||||
static const JanetReg cfuns[] = {
|
||||
@ -770,28 +758,22 @@ JanetTable *janet_core_env(void) {
|
||||
janet_gcroot(janet_wrap_table(env));
|
||||
|
||||
/* Load auxiliary envs */
|
||||
{
|
||||
JanetArgs args;
|
||||
args.n = 1;
|
||||
args.v = &ret;
|
||||
args.ret = &ret;
|
||||
janet_lib_io(args);
|
||||
janet_lib_math(args);
|
||||
janet_lib_array(args);
|
||||
janet_lib_tuple(args);
|
||||
janet_lib_buffer(args);
|
||||
janet_lib_table(args);
|
||||
janet_lib_fiber(args);
|
||||
janet_lib_os(args);
|
||||
janet_lib_parse(args);
|
||||
janet_lib_compile(args);
|
||||
janet_lib_debug(args);
|
||||
janet_lib_string(args);
|
||||
janet_lib_marsh(args);
|
||||
janet_lib_io(env);
|
||||
janet_lib_math(env);
|
||||
janet_lib_array(env);
|
||||
janet_lib_tuple(env);
|
||||
janet_lib_buffer(env);
|
||||
janet_lib_table(env);
|
||||
janet_lib_fiber(env);
|
||||
janet_lib_os(env);
|
||||
janet_lib_parse(env);
|
||||
janet_lib_compile(env);
|
||||
janet_lib_debug(env);
|
||||
janet_lib_string(env);
|
||||
janet_lib_marsh(env);
|
||||
#ifdef JANET_ASSEMBLER
|
||||
janet_lib_asm(args);
|
||||
janet_lib_asm(env);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Allow references to the environment */
|
||||
janet_def(env, "_env", ret, "The environment table for the current scope.");
|
||||
|
125
src/core/debug.c
125
src/core/debug.c
@ -29,26 +29,24 @@
|
||||
* out of the box. */
|
||||
|
||||
/* 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)
|
||||
return 1;
|
||||
janet_panic("invalid bytecode offset");
|
||||
def->bytecode[pc] |= 0x80;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
return 1;
|
||||
janet_panic("invalid bytecode offset");
|
||||
def->bytecode[pc] &= ~((uint32_t)0x80);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a location for a breakpoint given a source file an
|
||||
* location.
|
||||
*/
|
||||
int janet_debug_find(
|
||||
void janet_debug_find(
|
||||
JanetFuncDef **def_out, int32_t *pc_out,
|
||||
const uint8_t *source, int32_t offset) {
|
||||
/* Scan the heap for right func def */
|
||||
@ -84,9 +82,8 @@ int janet_debug_find(
|
||||
if (best_def) {
|
||||
*def_out = best_def;
|
||||
*pc_out = besti;
|
||||
return 0;
|
||||
} 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.
|
||||
* Takes a source file name and byte offset. */
|
||||
static int helper_find(JanetArgs args, JanetFuncDef **def, int32_t *bytecode_offset) {
|
||||
const uint8_t *source;
|
||||
int32_t source_offset;
|
||||
JANET_FIXARITY(args, 2);
|
||||
JANET_ARG_STRING(source, args, 0);
|
||||
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);
|
||||
static void helper_find(int32_t argc, Janet *argv, JanetFuncDef **def, int32_t *bytecode_offset) {
|
||||
janet_arity(argc, 2, 2);
|
||||
const uint8_t *source = janet_getstring(argv, 0);
|
||||
int32_t source_offset = janet_getinteger(argv, 1);
|
||||
janet_debug_find(def, bytecode_offset, source, source_offset);
|
||||
}
|
||||
|
||||
/* Helper to find funcdef and bytecode offset to insert or remove breakpoints.
|
||||
* Takes a function and byte offset*/
|
||||
static int helper_find_fun(JanetArgs args, JanetFuncDef **def, int32_t *bytecode_offset) {
|
||||
JanetFunction *func;
|
||||
int32_t offset = 0;
|
||||
JANET_MINARITY(args, 1);
|
||||
JANET_MAXARITY(args, 2);
|
||||
JANET_ARG_FUNCTION(func, args, 0);
|
||||
if (args.n == 2) {
|
||||
JANET_ARG_INTEGER(offset, args, 1);
|
||||
}
|
||||
static void helper_find_fun(int32_t argc, Janet *argv, JanetFuncDef **def, int32_t *bytecode_offset) {
|
||||
janet_arity(argc, 1, 2);
|
||||
JanetFunction *func = janet_getfunction(argv, 0);
|
||||
int32_t offset = (argc == 2) ? janet_getinteger(argv, 1) : 0;
|
||||
*def = func->def;
|
||||
*bytecode_offset = offset;
|
||||
JANET_RETURN_NIL(args);
|
||||
}
|
||||
|
||||
static int cfun_break(JanetArgs args) {
|
||||
static Janet cfun_break(int32_t argc, Janet *argv) {
|
||||
JanetFuncDef *def;
|
||||
int32_t offset;
|
||||
int status = helper_find(args, &def, &offset);
|
||||
if (status == 0) janet_debug_break(def, offset);
|
||||
return status;
|
||||
helper_find(argc, argv, &def, &offset);
|
||||
janet_debug_break(def, offset);
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
static int cfun_unbreak(JanetArgs args) {
|
||||
static Janet cfun_unbreak(int32_t argc, Janet *argv) {
|
||||
JanetFuncDef *def;
|
||||
int32_t offset;
|
||||
int status = helper_find(args, &def, &offset);
|
||||
if (status == 0) janet_debug_unbreak(def, offset);
|
||||
return status;
|
||||
helper_find(argc, argv, &def, &offset);
|
||||
janet_debug_unbreak(def, offset);
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
static int cfun_fbreak(JanetArgs args) {
|
||||
static Janet cfun_fbreak(int32_t argc, Janet *argv) {
|
||||
JanetFuncDef *def;
|
||||
int32_t offset;
|
||||
int status = helper_find_fun(args, &def, &offset);
|
||||
if (status == 0) {
|
||||
if (janet_debug_break(def, offset)) {
|
||||
JANET_THROW(args, "could not find breakpoint");
|
||||
}
|
||||
}
|
||||
return status;
|
||||
helper_find_fun(argc, argv, &def, &offset);
|
||||
janet_debug_break(def, offset);
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
static int cfun_unfbreak(JanetArgs args) {
|
||||
static Janet cfun_unfbreak(int32_t argc, Janet *argv) {
|
||||
JanetFuncDef *def;
|
||||
int32_t offset;
|
||||
int status = helper_find_fun(args, &def, &offset);
|
||||
if (status == 0) {
|
||||
if (janet_debug_unbreak(def, offset)) {
|
||||
JANET_THROW(args, "could not find breakpoint");
|
||||
}
|
||||
}
|
||||
return status;
|
||||
helper_find_fun(argc, argv, &def, &offset);
|
||||
janet_debug_unbreak(def, offset);
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
static int cfun_lineage(JanetArgs args) {
|
||||
JanetFiber *fiber;
|
||||
JanetArray *array;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_FIBER(fiber, args, 0);
|
||||
array = janet_array(0);
|
||||
static Janet cfun_lineage(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetFiber *fiber = janet_getfiber(argv, 0);
|
||||
JanetArray *array = janet_array(0);
|
||||
while (fiber) {
|
||||
janet_array_push(array, janet_wrap_fiber(fiber));
|
||||
fiber = fiber->child;
|
||||
}
|
||||
JANET_RETURN_ARRAY(args, array);
|
||||
return janet_wrap_array(array);
|
||||
}
|
||||
|
||||
/* Extract info from one stack frame */
|
||||
@ -224,12 +199,10 @@ static Janet doframe(JanetStackFrame *frame) {
|
||||
return janet_wrap_table(t);
|
||||
}
|
||||
|
||||
static int cfun_stack(JanetArgs args) {
|
||||
JanetFiber *fiber;
|
||||
JanetArray *array;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_FIBER(fiber, args, 0);
|
||||
array = janet_array(0);
|
||||
static Janet cfun_stack(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetFiber *fiber = janet_getfiber(argv, 0);
|
||||
JanetArray *array = janet_array(0);
|
||||
{
|
||||
int32_t i = fiber->frame;
|
||||
JanetStackFrame *frame;
|
||||
@ -239,18 +212,16 @@ static int cfun_stack(JanetArgs args) {
|
||||
i = frame->prevframe;
|
||||
}
|
||||
}
|
||||
JANET_RETURN_ARRAY(args, array);
|
||||
return janet_wrap_array(array);
|
||||
}
|
||||
|
||||
static int cfun_argstack(JanetArgs args) {
|
||||
JanetFiber *fiber;
|
||||
JanetArray *array;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_FIBER(fiber, args, 0);
|
||||
array = janet_array(fiber->stacktop - fiber->stackstart);
|
||||
static Janet cfun_argstack(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetFiber *fiber = janet_getfiber(argv, 0);
|
||||
JanetArray *array = janet_array(fiber->stacktop - fiber->stackstart);
|
||||
memcpy(array->data, fiber->data + fiber->stackstart, array->capacity * sizeof(Janet));
|
||||
array->count = array->capacity;
|
||||
JANET_RETURN_ARRAY(args, array);
|
||||
return janet_wrap_array(array);
|
||||
}
|
||||
|
||||
static const JanetReg cfuns[] = {
|
||||
@ -306,8 +277,6 @@ static const JanetReg cfuns[] = {
|
||||
};
|
||||
|
||||
/* Module entry point */
|
||||
int janet_lib_debug(JanetArgs args) {
|
||||
JanetTable *env = janet_env(args);
|
||||
void janet_lib_debug(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, cfuns);
|
||||
return 0;
|
||||
}
|
||||
|
@ -292,31 +292,29 @@ void janet_fiber_popframe(JanetFiber *fiber) {
|
||||
|
||||
/* 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;
|
||||
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->arity != 0) {
|
||||
JANET_THROW(args, "expected nullary function in fiber constructor");
|
||||
janet_panic("expected nullary function in fiber constructor");
|
||||
}
|
||||
}
|
||||
fiber = janet_fiber(func, 64);
|
||||
if (args.n == 2) {
|
||||
const uint8_t *flags;
|
||||
int32_t len, i;
|
||||
JANET_ARG_BYTES(flags, len, args, 1);
|
||||
if (argc == 2) {
|
||||
int32_t i;
|
||||
JanetByteView view = janet_getbytes(argv, 1);
|
||||
fiber->flags = 0;
|
||||
janet_fiber_set_status(fiber, JANET_STATUS_NEW);
|
||||
for (i = 0; i < len; i++) {
|
||||
if (flags[i] >= '0' && flags[i] <= '9') {
|
||||
fiber->flags |= JANET_FIBER_MASK_USERN(flags[i] - '0');
|
||||
for (i = 0; i < view.len; i++) {
|
||||
if (view.bytes[i] >= '0' && view.bytes[i] <= '9') {
|
||||
fiber->flags |= JANET_FIBER_MASK_USERN(view.bytes[i] - '0');
|
||||
} else {
|
||||
switch (flags[i]) {
|
||||
switch (view.bytes[i]) {
|
||||
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':
|
||||
fiber->flags |=
|
||||
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) {
|
||||
JanetFiber *fiber;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_FIBER(fiber, args, 0);
|
||||
static Janet cfun_status(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetFiber *fiber = janet_getfiber(argv, 0);
|
||||
uint32_t s = (fiber->flags & JANET_FIBER_STATUS_MASK) >>
|
||||
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) {
|
||||
JANET_FIXARITY(args, 0);
|
||||
JANET_RETURN_FIBER(args, janet_vm_fiber);
|
||||
static Janet cfun_current(int32_t argc, Janet *argv) {
|
||||
(void) argv;
|
||||
janet_arity(argc, 0, 0);
|
||||
return janet_wrap_fiber(janet_vm_fiber);
|
||||
}
|
||||
|
||||
static int cfun_maxstack(JanetArgs args) {
|
||||
JanetFiber *fiber;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_FIBER(fiber, args, 0);
|
||||
JANET_RETURN_INTEGER(args, fiber->maxstack);
|
||||
static Janet cfun_maxstack(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetFiber *fiber = janet_getfiber(argv, 0);
|
||||
return janet_wrap_integer(fiber->maxstack);
|
||||
}
|
||||
|
||||
static int cfun_setmaxstack(JanetArgs args) {
|
||||
JanetFiber *fiber;
|
||||
int32_t maxs;
|
||||
JANET_FIXARITY(args, 2);
|
||||
JANET_ARG_FIBER(fiber, args, 0);
|
||||
JANET_ARG_INTEGER(maxs, args, 1);
|
||||
static Janet cfun_setmaxstack(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 2, 2);
|
||||
JanetFiber *fiber = janet_getfiber(argv, 0);
|
||||
int32_t maxs = janet_getinteger(argv, 1);
|
||||
if (maxs < 0) {
|
||||
JANET_THROW(args, "expected positive integer");
|
||||
janet_panic("expected positive integer");
|
||||
}
|
||||
fiber->maxstack = maxs;
|
||||
JANET_RETURN_FIBER(args, fiber);
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static const JanetReg cfuns[] = {
|
||||
@ -425,8 +420,6 @@ static const JanetReg cfuns[] = {
|
||||
};
|
||||
|
||||
/* Module entry point */
|
||||
int janet_lib_fiber(JanetArgs args) {
|
||||
JanetTable *env = janet_env(args);
|
||||
void janet_lib_fiber(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, cfuns);
|
||||
return 0;
|
||||
}
|
||||
|
283
src/core/io.c
283
src/core/io.c
@ -53,13 +53,16 @@ JanetAbstractType janet_io_filetype = {
|
||||
};
|
||||
|
||||
/* Check argupments to fopen */
|
||||
static int checkflags(const uint8_t *str, int32_t len) {
|
||||
static int checkflags(const uint8_t *str) {
|
||||
int flags = 0;
|
||||
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) {
|
||||
default:
|
||||
return -1;
|
||||
janet_panicf("invalid flag %c, expected w, a, or r", *str);
|
||||
break;
|
||||
case 'w':
|
||||
flags |= IO_WRITE;
|
||||
break;
|
||||
@ -73,7 +76,8 @@ static int checkflags(const uint8_t *str, int32_t len) {
|
||||
for (i = 1; i < len; i++) {
|
||||
switch (str[i]) {
|
||||
default:
|
||||
return -1;
|
||||
janet_panicf("invalid flag %c, expected + or b", str[i]);
|
||||
break;
|
||||
case '+':
|
||||
if (flags & IO_UPDATE) return -1;
|
||||
flags |= IO_UPDATE;
|
||||
@ -87,41 +91,6 @@ static int checkflags(const uint8_t *str, int32_t len) {
|
||||
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) {
|
||||
IOFile *iof = (IOFile *) janet_abstract(&janet_io_filetype, sizeof(IOFile));
|
||||
iof->file = f;
|
||||
@ -130,97 +99,75 @@ static Janet makef(FILE *f, int flags) {
|
||||
}
|
||||
|
||||
/* Open a process */
|
||||
static int janet_io_popen(JanetArgs args) {
|
||||
const uint8_t *fname, *fmode;
|
||||
int32_t modelen;
|
||||
FILE *f;
|
||||
int flags;
|
||||
JANET_MINARITY(args, 1);
|
||||
JANET_MAXARITY(args, 2);
|
||||
JANET_ARG_STRING(fname, args, 0);
|
||||
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 {
|
||||
fmode = (const uint8_t *)"r";
|
||||
modelen = 1;
|
||||
static Janet janet_io_popen(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 2);
|
||||
const uint8_t *fname = janet_getstring(argv, 0);
|
||||
const uint8_t *fmode = NULL;
|
||||
if (argc == 2) {
|
||||
fmode = janet_getkeyword(argv, 1);
|
||||
if (janet_string_length(fmode) != 1 ||
|
||||
!(fmode[0] == 'r' || fmode[0] == 'w')) {
|
||||
janet_panicf("invalid file mode :%S, expected :r or :w", fmode);
|
||||
}
|
||||
}
|
||||
if (modelen != 1 || !(fmode[0] == 'r' || fmode[0] == 'w')) {
|
||||
JANET_THROW(args, "invalid file mode");
|
||||
}
|
||||
flags = (fmode[0] == 'r') ? IO_PIPED | IO_READ : IO_PIPED | IO_WRITE;
|
||||
int flags = (fmode && fmode[0] == '2')
|
||||
? IO_PIPED | IO_WRITE
|
||||
: IO_PIPED | IO_READ;
|
||||
#ifdef JANET_WINDOWS
|
||||
#define popen _popen
|
||||
#endif
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#define popen(A, B) (errno = 0, NULL)
|
||||
#endif
|
||||
f = popen((const char *)fname, (const char *)fmode);
|
||||
FILE *f = popen((const char *)fname, (const char *)fmode);
|
||||
if (!f) {
|
||||
if (errno == EMFILE) {
|
||||
JANET_THROW(args, "too many streams are open");
|
||||
}
|
||||
JANET_THROW(args, "could not open file");
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
JANET_RETURN(args, makef(f, flags));
|
||||
return makef(f, flags);
|
||||
}
|
||||
|
||||
/* Open a a file and return a userdata wrapper around the C file API. */
|
||||
static int janet_io_fopen(JanetArgs args) {
|
||||
const uint8_t *fname, *fmode;
|
||||
int32_t modelen;
|
||||
FILE *f;
|
||||
static Janet janet_io_fopen(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 2);
|
||||
const uint8_t *fname = janet_getstring(argv, 0);
|
||||
const uint8_t *fmode;
|
||||
int flags;
|
||||
JANET_MINARITY(args, 1);
|
||||
JANET_MAXARITY(args, 2);
|
||||
JANET_ARG_STRING(fname, args, 0);
|
||||
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);
|
||||
if (argc == 2) {
|
||||
fmode = janet_getkeyword(argv, 1);
|
||||
flags = checkflags(fmode);
|
||||
} else {
|
||||
fmode = (const uint8_t *)"r";
|
||||
modelen = 1;
|
||||
flags = IO_READ;
|
||||
}
|
||||
if ((flags = checkflags(fmode, modelen)) < 0) {
|
||||
JANET_THROW(args, "invalid file mode");
|
||||
}
|
||||
f = fopen((const char *)fname, (const char *)fmode);
|
||||
JANET_RETURN(args, f ? makef(f, flags) : janet_wrap_nil());
|
||||
FILE *f = fopen((const char *)fname, (const char *)fmode);
|
||||
return f ? makef(f, flags) : janet_wrap_nil();
|
||||
}
|
||||
|
||||
/* 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)))
|
||||
return "file is not readable";
|
||||
/* Ensure buffer size */
|
||||
if (janet_buffer_extra(buffer, nBytesMax))
|
||||
return "buffer overflow";
|
||||
janet_panic("file is not readable");
|
||||
janet_buffer_extra(buffer, nBytesMax);
|
||||
size_t ntoread = nBytesMax;
|
||||
size_t nread = fread((char *)(buffer->data + buffer->count), 1, ntoread, iof->file);
|
||||
if (nread != ntoread && ferror(iof->file))
|
||||
return "could not read file";
|
||||
janet_panic("could not read file");
|
||||
buffer->count += (int32_t) nread;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Read a certain number of bytes into memory */
|
||||
static int janet_io_fread(JanetArgs args) {
|
||||
JanetBuffer *b;
|
||||
IOFile *iof = checkfile(args, 0);
|
||||
if (!iof) return 1;
|
||||
if (iof->flags & IO_CLOSED)
|
||||
JANET_THROW(args, "file is closed");
|
||||
b = checkbuffer(args, 2, 1);
|
||||
if (!b) return 1;
|
||||
JANET_MINARITY(args, 2);
|
||||
if (janet_checktype(args.v[1], JANET_KEYWORD)) {
|
||||
const uint8_t *sym = janet_unwrap_symbol(args.v[1]);
|
||||
static Janet janet_io_fread(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");
|
||||
JanetBuffer *buffer;
|
||||
if (argc == 2) {
|
||||
buffer = janet_buffer(0);
|
||||
} else {
|
||||
buffer = janet_getbuffer(argv, 2);
|
||||
}
|
||||
if (janet_checktype(argv[1], JANET_KEYWORD)) {
|
||||
const uint8_t *sym = janet_unwrap_keyword(argv[1]);
|
||||
if (!janet_cstrcmp(sym, "all")) {
|
||||
/* Read whole file */
|
||||
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) */
|
||||
int32_t sizeBefore;
|
||||
do {
|
||||
sizeBefore = b->count;
|
||||
const char *maybeErr = read_chunk(iof, b, 1024);
|
||||
if (maybeErr) JANET_THROW(args, maybeErr);
|
||||
} while (sizeBefore < b->count);
|
||||
sizeBefore = buffer->count;
|
||||
read_chunk(iof, buffer, 1024);
|
||||
} while (sizeBefore < buffer->count);
|
||||
} else {
|
||||
fseek(iof->file, 0, SEEK_END);
|
||||
long fsize = ftell(iof->file);
|
||||
fseek(iof->file, 0, SEEK_SET);
|
||||
if (fsize > INT32_MAX) JANET_THROW(args, "buffer overflow");
|
||||
const char *maybeErr = read_chunk(iof, b, (int32_t) fsize);;
|
||||
if (maybeErr) JANET_THROW(args, maybeErr);
|
||||
read_chunk(iof, buffer, (int32_t) fsize);
|
||||
}
|
||||
} else if (!janet_cstrcmp(sym, "line")) {
|
||||
for (;;) {
|
||||
int x = fgetc(iof->file);
|
||||
if (x != EOF && janet_buffer_push_u8(b, (uint8_t)x))
|
||||
JANET_THROW(args, "buffer overflow");
|
||||
if (x != EOF) janet_buffer_push_u8(buffer, (uint8_t)x);
|
||||
if (x == EOF || x == '\n') break;
|
||||
}
|
||||
} 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 {
|
||||
int32_t len = janet_unwrap_integer(args.v[1]);
|
||||
if (len < 0) JANET_THROW(args, "expected positive integer");
|
||||
const char *maybeErr = read_chunk(iof, b, len);
|
||||
if (maybeErr) JANET_THROW(args, maybeErr);
|
||||
int32_t len = janet_getinteger(argv, 1);
|
||||
if (len < 0) janet_panic("expected positive integer");
|
||||
read_chunk(iof, buffer, len);
|
||||
}
|
||||
JANET_RETURN(args, janet_wrap_buffer(b));
|
||||
return janet_wrap_buffer(buffer);
|
||||
}
|
||||
|
||||
/* Write bytes to a file */
|
||||
static int janet_io_fwrite(JanetArgs args) {
|
||||
int32_t len, i;
|
||||
const uint8_t *str;
|
||||
IOFile *iof = checkfile(args, 0);
|
||||
if (!iof) return 1;
|
||||
static Janet janet_io_fwrite(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, -1);
|
||||
IOFile *iof = janet_getabstract(argv, 0, &janet_io_filetype);
|
||||
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)))
|
||||
JANET_THROW(args, "file is not writeable");
|
||||
for (i = 1; i < args.n; i++) {
|
||||
JANET_CHECKMANY(args, i, JANET_TFLAG_BYTES);
|
||||
}
|
||||
for (i = 1; i < args.n; i++) {
|
||||
JANET_ARG_BYTES(str, len, args, i);
|
||||
if (len) {
|
||||
if (!fwrite(str, len, 1, iof->file)) JANET_THROW(args, "error writing to file");
|
||||
janet_panic("file is not writeable");
|
||||
int32_t i;
|
||||
/* Verify all arguments before writing to file */
|
||||
for (i = 1; i < argc; i++)
|
||||
janet_getbytes(argv, i);
|
||||
for (i = 1; i < argc; i++) {
|
||||
JanetByteView view = janet_getbytes(argv, i);
|
||||
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 */
|
||||
static int janet_io_fflush(JanetArgs args) {
|
||||
IOFile *iof = checkfile(args, 0);
|
||||
if (!iof) return 1;
|
||||
static Janet janet_io_fflush(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
IOFile *iof = janet_getabstract(argv, 0, &janet_io_filetype);
|
||||
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)))
|
||||
JANET_THROW(args, "file is not flushable");
|
||||
if (fflush(iof->file)) JANET_THROW(args, "could not flush file");
|
||||
JANET_RETURN(args, janet_wrap_abstract(iof));
|
||||
janet_panic("file is not writeable");
|
||||
if (fflush(iof->file))
|
||||
janet_panic("could not flush file");
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
/* Cleanup a file */
|
||||
@ -306,38 +248,35 @@ static int janet_io_gc(void *p, size_t len) {
|
||||
}
|
||||
|
||||
/* Close a file */
|
||||
static int janet_io_fclose(JanetArgs args) {
|
||||
IOFile *iof = checkfile(args, 0);
|
||||
if (!iof) return 1;
|
||||
if (iof->flags & (IO_CLOSED))
|
||||
JANET_THROW(args, "file already closed");
|
||||
static Janet janet_io_fclose(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
IOFile *iof = janet_getabstract(argv, 0, &janet_io_filetype);
|
||||
if (iof->flags & IO_CLOSED)
|
||||
janet_panic("file is closed");
|
||||
if (iof->flags & (IO_NOT_CLOSEABLE))
|
||||
JANET_THROW(args, "file not closable");
|
||||
janet_panic("file not closable");
|
||||
if (iof->flags & IO_PIPED) {
|
||||
#ifdef JANET_WINDOWS
|
||||
#define pclose _pclose
|
||||
#endif
|
||||
if (pclose(iof->file)) JANET_THROW(args, "could not close file");
|
||||
if (pclose(iof->file)) janet_panic("could not close file");
|
||||
} 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;
|
||||
JANET_RETURN(args, janet_wrap_abstract(iof));
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
/* 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;
|
||||
int whence = SEEK_CUR;
|
||||
IOFile *iof = checkfile(args, 0);
|
||||
if (!iof) return 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 (argc >= 2) {
|
||||
const uint8_t *whence_sym = janet_getkeyword(argv, 1);
|
||||
if (!janet_cstrcmp(whence_sym, "cur")) {
|
||||
whence = SEEK_CUR;
|
||||
} 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")) {
|
||||
whence = SEEK_END;
|
||||
} 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) {
|
||||
double doffset;
|
||||
JANET_ARG_NUMBER(doffset, args, 2);
|
||||
offset = (long int)doffset;
|
||||
if (argc == 3) {
|
||||
offset = janet_getinteger64(argv, 2);
|
||||
}
|
||||
}
|
||||
if (fseek(iof->file, offset, whence))
|
||||
JANET_THROW(args, "error seeking file");
|
||||
JANET_RETURN(args, args.v[0]);
|
||||
if (fseek(iof->file, offset, whence)) janet_panic("error seeking file");
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static const JanetReg cfuns[] = {
|
||||
@ -420,25 +356,18 @@ static const JanetReg cfuns[] = {
|
||||
};
|
||||
|
||||
/* Module entry point */
|
||||
int janet_lib_io(JanetArgs args) {
|
||||
JanetTable *env = janet_env(args);
|
||||
void janet_lib_io(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, cfuns);
|
||||
|
||||
/* stdout */
|
||||
janet_def(env, "stdout",
|
||||
makef(stdout, IO_APPEND | IO_NOT_CLOSEABLE | IO_SERIALIZABLE),
|
||||
"The standard output file.");
|
||||
|
||||
|
||||
/* stderr */
|
||||
janet_def(env, "stderr",
|
||||
makef(stderr, IO_APPEND | IO_NOT_CLOSEABLE | IO_SERIALIZABLE),
|
||||
"The standard error file.");
|
||||
|
||||
/* stdin */
|
||||
janet_def(env, "stdin",
|
||||
makef(stdin, IO_READ | IO_NOT_CLOSEABLE | IO_SERIALIZABLE),
|
||||
"The standard input file.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -21,7 +21,6 @@
|
||||
*/
|
||||
|
||||
#include <janet/janet.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "state.h"
|
||||
#include "vector.h"
|
||||
@ -124,7 +123,7 @@ JanetTable *janet_env_lookup(JanetTable *env) {
|
||||
/* Marshal an integer onto the buffer */
|
||||
static void pushint(MarshalState *st, int32_t x) {
|
||||
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 {
|
||||
uint8_t intbuf[5];
|
||||
intbuf[0] = LB_INTEGER;
|
||||
@ -132,16 +131,16 @@ static void pushint(MarshalState *st, int32_t x) {
|
||||
intbuf[2] = (x >> 8) & 0xFF;
|
||||
intbuf[3] = (x >> 16) & 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) {
|
||||
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) {
|
||||
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. */
|
||||
@ -1102,61 +1101,46 @@ int janet_unmarshal(
|
||||
|
||||
/* C functions */
|
||||
|
||||
static int cfun_env_lookup(JanetArgs args) {
|
||||
JanetTable *env;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_TABLE(env, args, 0);
|
||||
JANET_RETURN_TABLE(args, janet_env_lookup(env));
|
||||
static Janet cfun_env_lookup(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetTable *env = janet_gettable(argv, 0);
|
||||
return janet_wrap_table(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;
|
||||
JanetTable *rreg;
|
||||
JanetTable *rreg = NULL;
|
||||
Janet err_param = janet_wrap_nil();
|
||||
int status;
|
||||
JANET_MINARITY(args, 1);
|
||||
JANET_MAXARITY(args, 3);
|
||||
if (args.n > 1) {
|
||||
/* Reverse Registry provided */
|
||||
JANET_ARG_TABLE(rreg, args, 1);
|
||||
} else {
|
||||
rreg = NULL;
|
||||
if (argc > 1) {
|
||||
rreg = janet_gettable(argv, 1);
|
||||
}
|
||||
if (args.n > 2) {
|
||||
/* Buffer provided */
|
||||
JANET_ARG_BUFFER(buffer, args, 2);
|
||||
if (argc > 2) {
|
||||
buffer = janet_getbuffer(argv, 2);
|
||||
} else {
|
||||
buffer = janet_buffer(10);
|
||||
}
|
||||
status = janet_marshal(buffer, args.v[0], &err_param, rreg, 0);
|
||||
if (status) {
|
||||
const uint8_t *errstr = janet_formatc(
|
||||
"%s for %V",
|
||||
mr_strings[status],
|
||||
err_param);
|
||||
JANET_THROWV(args, janet_wrap_string(errstr));
|
||||
}
|
||||
JANET_RETURN_BUFFER(args, buffer);
|
||||
status = janet_marshal(buffer, argv[0], &err_param, rreg, 0);
|
||||
if (status)
|
||||
janet_panicf("%s for %V", mr_strings[status], err_param);
|
||||
return janet_wrap_buffer(buffer);
|
||||
}
|
||||
|
||||
static int cfun_unmarshal(JanetArgs args) {
|
||||
const uint8_t *bytes;
|
||||
JanetTable *reg;
|
||||
int32_t len;
|
||||
static Janet cfun_unmarshal(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 2);
|
||||
JanetByteView view = janet_getbytes(argv, 0);
|
||||
JanetTable *reg = NULL;
|
||||
Janet ret;
|
||||
int status;
|
||||
JANET_MINARITY(args, 1);
|
||||
JANET_MAXARITY(args, 2);
|
||||
JANET_ARG_BYTES(bytes, len, args, 0);
|
||||
if (args.n > 1) {
|
||||
JANET_ARG_TABLE(reg, args, 1);
|
||||
} else {
|
||||
reg = NULL;
|
||||
if (argc > 1) {
|
||||
reg = janet_gettable(argv, 1);
|
||||
}
|
||||
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) {
|
||||
JANET_THROW(args, umr_strings[status]);
|
||||
janet_panic(umr_strings[status]);
|
||||
}
|
||||
return JANET_SIGNAL_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const JanetReg cfuns[] = {
|
||||
@ -1185,8 +1169,6 @@ static const JanetReg cfuns[] = {
|
||||
};
|
||||
|
||||
/* Module entry point */
|
||||
int janet_lib_marsh(JanetArgs args) {
|
||||
JanetTable *env = janet_env(args);
|
||||
void janet_lib_marsh(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, cfuns);
|
||||
return 0;
|
||||
}
|
||||
|
@ -24,35 +24,33 @@
|
||||
#include <math.h>
|
||||
|
||||
/* Get a random number */
|
||||
int janet_rand(JanetArgs args) {
|
||||
JANET_FIXARITY(args, 0);
|
||||
Janet janet_rand(int32_t argc, Janet *argv) {
|
||||
(void) argv;
|
||||
janet_arity(argc, 0, 0);
|
||||
double r = (rand() % RAND_MAX) / ((double) RAND_MAX);
|
||||
JANET_RETURN_NUMBER(args, r);
|
||||
return janet_wrap_number(r);
|
||||
}
|
||||
|
||||
/* Seed the random number generator */
|
||||
int janet_srand(JanetArgs args) {
|
||||
int32_t x = 0;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_INTEGER(x, args, 0);
|
||||
Janet janet_srand(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
int32_t x = janet_getinteger(argv, 0);
|
||||
srand((unsigned) x);
|
||||
return 0;
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
int janet_remainder(JanetArgs args) {
|
||||
JANET_FIXARITY(args, 2);
|
||||
double x, y;
|
||||
JANET_ARG_NUMBER(x, args, 0);
|
||||
JANET_ARG_NUMBER(y, args, 1);
|
||||
JANET_RETURN_NUMBER(args, fmod(x, y));
|
||||
Janet janet_remainder(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 2, 2);
|
||||
double x = janet_getnumber(argv, 0);
|
||||
double y = janet_getnumber(argv, 1);
|
||||
return janet_wrap_number(fmod(x, y));
|
||||
}
|
||||
|
||||
#define JANET_DEFINE_MATHOP(name, fop)\
|
||||
int janet_##name(JanetArgs args) {\
|
||||
double x;\
|
||||
JANET_FIXARITY(args, 1);\
|
||||
JANET_ARG_NUMBER(x, args, 0);\
|
||||
JANET_RETURN_NUMBER(args, fop(x));\
|
||||
Janet janet_##name(int32_t argc, Janet *argv) {\
|
||||
janet_arity(argc, 1, 1); \
|
||||
double x = janet_getnumber(argv, 0); \
|
||||
return janet_wrap_number(fop(x)); \
|
||||
}
|
||||
|
||||
JANET_DEFINE_MATHOP(acos, acos)
|
||||
@ -73,20 +71,19 @@ JANET_DEFINE_MATHOP(fabs, fabs)
|
||||
JANET_DEFINE_MATHOP(floor, floor)
|
||||
|
||||
#define JANET_DEFINE_MATH2OP(name, fop)\
|
||||
int janet_##name(JanetArgs args) {\
|
||||
double lhs, rhs;\
|
||||
JANET_FIXARITY(args, 2);\
|
||||
JANET_ARG_NUMBER(lhs, args, 0);\
|
||||
JANET_ARG_NUMBER(rhs, args, 1);\
|
||||
JANET_RETURN_NUMBER(args, fop(lhs, rhs));\
|
||||
Janet janet_##name(int32_t argc, Janet *argv) {\
|
||||
janet_arity(argc, 2, 2); \
|
||||
double lhs = janet_getnumber(argv, 0); \
|
||||
double rhs = janet_getnumber(argv, 1); \
|
||||
return janet_wrap_number(fop(lhs, rhs)); \
|
||||
}\
|
||||
|
||||
JANET_DEFINE_MATH2OP(atan2, atan2)
|
||||
JANET_DEFINE_MATH2OP(pow, pow)
|
||||
|
||||
static int janet_not(JanetArgs args) {
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_RETURN_BOOLEAN(args, !janet_truthy(args.v[0]));
|
||||
static Janet janet_not(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
return janet_wrap_boolean(!janet_truthy(argv[0]));
|
||||
}
|
||||
|
||||
static const JanetReg cfuns[] = {
|
||||
@ -162,15 +159,12 @@ static const JanetReg cfuns[] = {
|
||||
};
|
||||
|
||||
/* Module entry point */
|
||||
int janet_lib_math(JanetArgs args) {
|
||||
JanetTable *env = janet_env(args);
|
||||
void janet_lib_math(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, cfuns);
|
||||
|
||||
janet_def(env, "math/pi", janet_wrap_number(3.1415926535897931),
|
||||
"The value pi.");
|
||||
janet_def(env, "math/e", janet_wrap_number(2.7182818284590451),
|
||||
"The base of the natural log.");
|
||||
janet_def(env, "math/inf", janet_wrap_number(INFINITY),
|
||||
"The number representing positive infinity");
|
||||
return 0;
|
||||
}
|
||||
|
159
src/core/os.c
159
src/core/os.c
@ -40,27 +40,28 @@
|
||||
#include <mach/mach.h>
|
||||
#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
|
||||
JANET_RETURN_CKEYWORD(args, "windows");
|
||||
return janet_ckeywordv("windows");
|
||||
#elif __APPLE__
|
||||
JANET_RETURN_CKEYWORD(args, "macos");
|
||||
return janet_ckeywordv("macos");
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
JANET_RETURN_CKEYWORD(args, "web");
|
||||
return janet_ckeywordv("web");
|
||||
#else
|
||||
JANET_RETURN_CKEYWORD(args, "posix");
|
||||
return janet_ckeywordv("posix");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef JANET_WINDOWS
|
||||
static int os_execute(JanetArgs args) {
|
||||
JANET_MINARITY(args, 1);
|
||||
static Janet os_execute(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, -1);
|
||||
JanetBuffer *buffer = janet_buffer(10);
|
||||
for (int32_t i = 0; i < args.n; i++) {
|
||||
const uint8_t *argstring;
|
||||
JANET_ARG_STRING(argstring, args, i);
|
||||
for (int32_t i = 0; i < argc; i++) {
|
||||
const uint8_t *argstring = janet_getstring(argv, i);
|
||||
janet_buffer_push_bytes(buffer, argstring, janet_string_length(argstring));
|
||||
if (i != args.n - 1) {
|
||||
if (i != argc - 1) {
|
||||
janet_buffer_push_u8(buffer, ' ');
|
||||
}
|
||||
}
|
||||
@ -80,7 +81,7 @@ static int os_execute(JanetArgs args) {
|
||||
buffer->count);
|
||||
if (nwritten == 0) {
|
||||
free(sys_str);
|
||||
JANET_THROW(args, "could not create process");
|
||||
janet_panic("could not create process");
|
||||
}
|
||||
|
||||
STARTUPINFO si;
|
||||
@ -102,7 +103,7 @@ static int os_execute(JanetArgs args) {
|
||||
&si,
|
||||
&pi)) {
|
||||
free(sys_str);
|
||||
JANET_THROW(args, "could not create process");
|
||||
janet_panic("could not create process");
|
||||
}
|
||||
free(sys_str);
|
||||
|
||||
@ -114,61 +115,57 @@ static int os_execute(JanetArgs args) {
|
||||
GetExitCodeProcess(pi.hProcess, (LPDWORD)&status);
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
JANET_RETURN_INTEGER(args, (int32_t)status);
|
||||
return janet_wrap_integer(status);
|
||||
}
|
||||
#else
|
||||
static int os_execute(JanetArgs args) {
|
||||
JANET_MINARITY(args, 1);
|
||||
const uint8_t **argv = malloc(sizeof(uint8_t *) * (args.n + 1));
|
||||
if (NULL == argv) {
|
||||
static Janet os_execute(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, -1);
|
||||
const uint8_t **child_argv = malloc(sizeof(uint8_t *) * (argc + 1));
|
||||
if (NULL == child_argv) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
for (int32_t i = 0; i < args.n; i++) {
|
||||
JANET_ARG_STRING(argv[i], args, i);
|
||||
for (int32_t i = 0; i < argc; i++) {
|
||||
child_argv[i] = janet_getstring(argv, i);
|
||||
}
|
||||
argv[args.n] = NULL;
|
||||
child_argv[argc] = NULL;
|
||||
|
||||
/* Fork child process */
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
JANET_THROW(args, "failed to execute");
|
||||
janet_panic("failed to execute");
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
JANET_RETURN_INTEGER(args, status);
|
||||
return janet_wrap_integer(status);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int os_shell(JanetArgs args) {
|
||||
int nofirstarg = (args.n < 1 || !janet_checktype(args.v[0], JANET_STRING));
|
||||
const char *cmd = nofirstarg
|
||||
? NULL
|
||||
: (const char *) janet_unwrap_string(args.v[0]);
|
||||
static Janet os_shell(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 0, 1);
|
||||
const char *cmd = argc
|
||||
? (const char *)janet_getstring(argv, 0)
|
||||
: NULL;
|
||||
int stat = system(cmd);
|
||||
JANET_RETURN(args, cmd
|
||||
? janet_wrap_integer(stat)
|
||||
: janet_wrap_boolean(stat));
|
||||
return argc
|
||||
? janet_wrap_integer(stat)
|
||||
: janet_wrap_boolean(stat);
|
||||
}
|
||||
|
||||
static int os_getenv(JanetArgs args) {
|
||||
const uint8_t *k;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_STRING(k, args, 0);
|
||||
static Janet os_getenv(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
const uint8_t *k = janet_getstring(argv, 0);
|
||||
const char *cstr = (const char *) k;
|
||||
const char *res = getenv(cstr);
|
||||
if (!res) {
|
||||
JANET_RETURN_NIL(args);
|
||||
}
|
||||
JANET_RETURN(args, cstr
|
||||
? janet_cstringv(res)
|
||||
: janet_wrap_nil());
|
||||
return (res && 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
|
||||
#define SETENV(K,V) _putenv_s(K, V)
|
||||
#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 UNSETENV(K) unsetenv(K)
|
||||
#endif
|
||||
const uint8_t *k;
|
||||
const char *ks;
|
||||
JANET_MAXARITY(args, 2);
|
||||
JANET_MINARITY(args, 1);
|
||||
JANET_ARG_STRING(k, args, 0);
|
||||
ks = (const char *) k;
|
||||
if (args.n == 1 || janet_checktype(args.v[1], JANET_NIL)) {
|
||||
janet_arity(argc, 1, 2);
|
||||
const uint8_t *k = janet_getstring(argv, 0);
|
||||
const char *ks = (const char *) k;
|
||||
if (argc == 1 || janet_checktype(argv[1], JANET_NIL)) {
|
||||
UNSETENV(ks);
|
||||
} else {
|
||||
const uint8_t *v;
|
||||
JANET_ARG_STRING(v, args, 1);
|
||||
const char *vc = (const char *) v;
|
||||
SETENV(ks, vc);
|
||||
const uint8_t *v = janet_getstring(argv, 1);
|
||||
SETENV(ks, (const char *)v);
|
||||
}
|
||||
return 0;
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
static int os_exit(JanetArgs args) {
|
||||
JANET_MAXARITY(args, 1);
|
||||
if (args.n == 0) {
|
||||
static Janet os_exit(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 0, 1);
|
||||
if (argc == 0) {
|
||||
exit(EXIT_SUCCESS);
|
||||
} else if (janet_checkint(args.v[0])) {
|
||||
exit(janet_unwrap_integer(args.v[0]));
|
||||
} else if (janet_checkint(argv[0])) {
|
||||
exit(janet_unwrap_integer(argv[0]));
|
||||
} else {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return 0;
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
static int os_time(JanetArgs args) {
|
||||
JANET_FIXARITY(args, 0);
|
||||
static Janet os_time(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 0, 0);
|
||||
(void) argv;
|
||||
double dtime = (double)(time(NULL));
|
||||
JANET_RETURN_NUMBER(args, dtime);
|
||||
return janet_wrap_number(dtime);
|
||||
}
|
||||
|
||||
/* Clock shims */
|
||||
@ -238,22 +231,19 @@ static int gettime(struct timespec *spec) {
|
||||
#define gettime(TV) clock_gettime(CLOCK_MONOTONIC, (TV))
|
||||
#endif
|
||||
|
||||
static int os_clock(JanetArgs args) {
|
||||
JANET_FIXARITY(args, 0);
|
||||
static Janet os_clock(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 0, 0);
|
||||
(void) argv;
|
||||
struct timespec tv;
|
||||
if (gettime(&tv))
|
||||
JANET_THROW(args, "could not get time");
|
||||
if (gettime(&tv)) janet_panic("could not get time");
|
||||
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) {
|
||||
double delay;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_NUMBER(delay, args, 0);
|
||||
if (delay < 0) {
|
||||
JANET_THROW(args, "invalid argument to sleep");
|
||||
}
|
||||
static Janet os_sleep(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
double delay = janet_getnumber(argv, 0);
|
||||
if (delay < 0) janet_panic("invalid argument to sleep");
|
||||
#ifdef JANET_WINDOWS
|
||||
Sleep((DWORD) (delay * 1000));
|
||||
#else
|
||||
@ -264,11 +254,12 @@ static int os_sleep(JanetArgs args) {
|
||||
: 0;
|
||||
nanosleep(&ts, NULL);
|
||||
#endif
|
||||
return 0;
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
static int os_cwd(JanetArgs args) {
|
||||
JANET_FIXARITY(args, 0);
|
||||
static Janet os_cwd(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 0, 0);
|
||||
(void) argv;
|
||||
char buf[FILENAME_MAX];
|
||||
char *ptr;
|
||||
#ifdef JANET_WINDOWS
|
||||
@ -276,10 +267,8 @@ static int os_cwd(JanetArgs args) {
|
||||
#else
|
||||
ptr = getcwd(buf, FILENAME_MAX);
|
||||
#endif
|
||||
if (NULL == ptr) {
|
||||
JANET_THROW(args, "could not get current directory");
|
||||
}
|
||||
JANET_RETURN_CSTRING(args, ptr);
|
||||
if (NULL == ptr) janet_panic("could not get current directory");
|
||||
return janet_cstringv(ptr);
|
||||
}
|
||||
|
||||
static const JanetReg cfuns[] = {
|
||||
@ -335,8 +324,6 @@ static const JanetReg cfuns[] = {
|
||||
};
|
||||
|
||||
/* Module entry point */
|
||||
int janet_lib_os(JanetArgs args) {
|
||||
JanetTable *env = janet_env(args);
|
||||
void janet_lib_os(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, cfuns);
|
||||
return 0;
|
||||
}
|
||||
|
149
src/core/parse.c
149
src/core/parse.c
@ -620,79 +620,58 @@ static JanetAbstractType janet_parse_parsertype = {
|
||||
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 */
|
||||
static int cfun_parser(JanetArgs args) {
|
||||
JANET_FIXARITY(args, 0);
|
||||
static Janet cfun_parser(int32_t argc, Janet *argv) {
|
||||
(void) argv;
|
||||
janet_arity(argc, 0, 0);
|
||||
JanetParser *p = janet_abstract(&janet_parse_parsertype, sizeof(JanetParser));
|
||||
janet_parser_init(p);
|
||||
JANET_RETURN_ABSTRACT(args, p);
|
||||
return janet_wrap_abstract(p);
|
||||
}
|
||||
|
||||
static int cfun_consume(JanetArgs args) {
|
||||
const uint8_t *bytes;
|
||||
int32_t len;
|
||||
JanetParser *p;
|
||||
int32_t i;
|
||||
JANET_MINARITY(args, 2);
|
||||
JANET_MAXARITY(args, 3);
|
||||
JANET_CHECKABSTRACT(args, 0, &janet_parse_parsertype);
|
||||
p = (JanetParser *) janet_unwrap_abstract(args.v[0]);
|
||||
JANET_ARG_BYTES(bytes, len, args, 1);
|
||||
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;
|
||||
static Janet cfun_consume(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 2, 3);
|
||||
JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
|
||||
JanetByteView view = janet_getbytes(argv, 1);
|
||||
if (argc == 3) {
|
||||
int32_t offset = janet_getinteger(argv, 2);
|
||||
if (offset < 0 || offset > view.len)
|
||||
janet_panicf("invalid offset %d out of range [0,%d]", offset, view.len);
|
||||
view.len -= offset;
|
||||
view.bytes += offset;
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
janet_parser_consume(p, bytes[i]);
|
||||
int32_t i;
|
||||
for (i = 0; i < view.len; i++) {
|
||||
janet_parser_consume(p, view.bytes[i]);
|
||||
switch (janet_parser_status(p)) {
|
||||
case JANET_PARSE_ROOT:
|
||||
case JANET_PARSE_PENDING:
|
||||
break;
|
||||
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) {
|
||||
JanetParser *p;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_CHECKABSTRACT(args, 0, &janet_parse_parsertype);
|
||||
p = (JanetParser *) janet_unwrap_abstract(args.v[0]);
|
||||
JANET_RETURN_BOOLEAN(args, janet_parser_has_more(p));
|
||||
static Janet cfun_has_more(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
|
||||
return janet_wrap_boolean(janet_parser_has_more(p));
|
||||
}
|
||||
|
||||
static int cfun_byte(JanetArgs args) {
|
||||
int32_t i;
|
||||
JanetParser *p;
|
||||
JANET_FIXARITY(args, 2);
|
||||
JANET_CHECKABSTRACT(args, 0, &janet_parse_parsertype);
|
||||
p = (JanetParser *) janet_unwrap_abstract(args.v[0]);
|
||||
JANET_ARG_INTEGER(i, args, 1);
|
||||
static Janet cfun_byte(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 2, 2);
|
||||
JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
|
||||
int32_t i = janet_getinteger(argv, 1);
|
||||
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;
|
||||
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)) {
|
||||
case JANET_PARSE_PENDING:
|
||||
stat = "pending";
|
||||
@ -704,58 +683,42 @@ static int cfun_status(JanetArgs args) {
|
||||
stat = "root";
|
||||
break;
|
||||
}
|
||||
JANET_RETURN_CKEYWORD(args, stat);
|
||||
return janet_ckeywordv(stat);
|
||||
}
|
||||
|
||||
static int cfun_error(JanetArgs args) {
|
||||
const char *err;
|
||||
JanetParser *p;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_CHECKABSTRACT(args, 0, &janet_parse_parsertype);
|
||||
p = (JanetParser *) janet_unwrap_abstract(args.v[0]);
|
||||
err = janet_parser_error(p);
|
||||
if (err) {
|
||||
JANET_RETURN_CSTRING(args, err);
|
||||
} else {
|
||||
JANET_RETURN_NIL(args);
|
||||
}
|
||||
static Janet cfun_error(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
|
||||
const char *err = janet_parser_error(p);
|
||||
if (err) return janet_cstringv(err);
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
static int cfun_produce(JanetArgs args) {
|
||||
Janet val;
|
||||
JanetParser *p;
|
||||
JANET_FIXARITY(args, 1);
|
||||
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 Janet cfun_produce(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
|
||||
return janet_parser_produce(p);
|
||||
}
|
||||
|
||||
static int cfun_flush(JanetArgs args) {
|
||||
JanetParser *p;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_CHECKABSTRACT(args, 0, &janet_parse_parsertype);
|
||||
p = (JanetParser *) janet_unwrap_abstract(args.v[0]);
|
||||
static Janet cfun_flush(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
|
||||
janet_parser_flush(p);
|
||||
JANET_RETURN(args, args.v[0]);
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static int cfun_where(JanetArgs args) {
|
||||
JanetParser *p;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_CHECKABSTRACT(args, 0, &janet_parse_parsertype);
|
||||
p = (JanetParser *) janet_unwrap_abstract(args.v[0]);
|
||||
JANET_RETURN_INTEGER(args, p->offset);
|
||||
static Janet cfun_where(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
|
||||
return janet_wrap_integer(p->offset);
|
||||
}
|
||||
|
||||
static int cfun_state(JanetArgs args) {
|
||||
static Janet cfun_state(int32_t argc, Janet *argv) {
|
||||
size_t i;
|
||||
const uint8_t *str;
|
||||
size_t oldcount;
|
||||
JanetParser *p;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_CHECKABSTRACT(args, 0, &janet_parse_parsertype);
|
||||
p = (JanetParser *) janet_unwrap_abstract(args.v[0]);
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
|
||||
oldcount = p->bufcount;
|
||||
for (i = 0; i < p->statecount; 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));
|
||||
p->bufcount = oldcount;
|
||||
JANET_RETURN_STRING(args, str);
|
||||
return janet_wrap_string(str);
|
||||
}
|
||||
|
||||
static const JanetReg cfuns[] = {
|
||||
@ -843,8 +806,6 @@ static const JanetReg cfuns[] = {
|
||||
};
|
||||
|
||||
/* Load the library */
|
||||
int janet_lib_parse(JanetArgs args) {
|
||||
JanetTable *env = janet_env(args);
|
||||
void janet_lib_parse(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, cfuns);
|
||||
return 0;
|
||||
}
|
||||
|
@ -825,185 +825,125 @@ static int32_t kmp_next(struct kmp_state *state) {
|
||||
|
||||
/* CFuns */
|
||||
|
||||
static int cfun_slice(JanetArgs args) {
|
||||
const uint8_t *data;
|
||||
int32_t len, start, end;
|
||||
const uint8_t *ret;
|
||||
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 Janet cfun_slice(int32_t argc, Janet *argv) {
|
||||
JanetRange range = janet_getslice(argc, argv);
|
||||
JanetByteView view = janet_getbytes(argv, 0);
|
||||
return janet_stringv(view.bytes + range.start, range.end - range.start);
|
||||
}
|
||||
|
||||
static int cfun_repeat(JanetArgs args) {
|
||||
const uint8_t *data;
|
||||
uint8_t *newbuf, *p, *end;
|
||||
int32_t len, rep;
|
||||
int64_t mulres;
|
||||
JANET_FIXARITY(args, 2);
|
||||
JANET_ARG_BYTES(data, len, args, 0);
|
||||
JANET_ARG_INTEGER(rep, args, 1);
|
||||
if (rep < 0) {
|
||||
JANET_THROW(args, "expected non-negative number of repetitions");
|
||||
} else if (rep == 0) {
|
||||
JANET_RETURN_CSTRING(args, "");
|
||||
static Janet cfun_repeat(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 2, 2);
|
||||
JanetByteView view = janet_getbytes(argv, 0);
|
||||
int32_t rep = janet_getinteger(argv, 1);
|
||||
if (rep < 0) janet_panic("expected non-negative number of repetitions");
|
||||
if (rep == 0) return janet_cstringv("");
|
||||
int64_t mulres = (int64_t) rep * view.len;
|
||||
if (mulres > INT32_MAX) janet_panic("result string is too long");
|
||||
uint8_t *newbuf = janet_string_begin((int32_t) mulres);
|
||||
uint8_t *end = newbuf + mulres;
|
||||
uint8_t *p = newbuf;
|
||||
for (p = newbuf; p < end; p += view.len) {
|
||||
memcpy(p, view.bytes, view.len);
|
||||
}
|
||||
mulres = (int64_t) rep * len;
|
||||
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));
|
||||
return janet_wrap_string(janet_string_end(newbuf));
|
||||
}
|
||||
|
||||
static int cfun_bytes(JanetArgs args) {
|
||||
const uint8_t *str;
|
||||
int32_t strlen, i;
|
||||
Janet *tup;
|
||||
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) {
|
||||
static Janet cfun_bytes(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetByteView view = janet_getbytes(argv, 0);
|
||||
Janet *tup = janet_tuple_begin(view.len);
|
||||
int32_t i;
|
||||
uint8_t *buf;
|
||||
for (i = 0; i < args.n; i++) {
|
||||
if (!janet_checkint(args.v[i])) {
|
||||
JANET_THROW(args, "expected integer byte values");
|
||||
}
|
||||
for (i = 0; i < view.len; i++) {
|
||||
tup[i] = janet_wrap_integer((int32_t) view.bytes[i]);
|
||||
}
|
||||
buf = janet_string_begin(args.n);
|
||||
for (i = 0; i < args.n; i++) {
|
||||
int32_t c;
|
||||
JANET_ARG_INTEGER(c, args, i);
|
||||
return janet_wrap_tuple(janet_tuple_end(tup));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
JANET_RETURN_STRING(args, janet_string_end(buf));
|
||||
return janet_wrap_string(janet_string_end(buf));
|
||||
}
|
||||
|
||||
static int cfun_asciilower(JanetArgs args) {
|
||||
const uint8_t *str;
|
||||
uint8_t *buf;
|
||||
int32_t len, i;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_BYTES(str, len, args, 0);
|
||||
buf = janet_string_begin(len);
|
||||
for (i = 0; i < len; i++) {
|
||||
uint8_t c = str[i];
|
||||
static Janet cfun_asciilower(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetByteView view = janet_getbytes(argv, 0);
|
||||
uint8_t *buf = janet_string_begin(view.len);
|
||||
for (int32_t i = 0; i < view.len; i++) {
|
||||
uint8_t c = view.bytes[i];
|
||||
if (c >= 65 && c <= 90) {
|
||||
buf[i] = c + 32;
|
||||
} else {
|
||||
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) {
|
||||
const uint8_t *str;
|
||||
uint8_t *buf;
|
||||
int32_t len, i;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_BYTES(str, len, args, 0);
|
||||
buf = janet_string_begin(len);
|
||||
for (i = 0; i < len; i++) {
|
||||
uint8_t c = str[i];
|
||||
static Janet cfun_asciiupper(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetByteView view = janet_getbytes(argv, 0);
|
||||
uint8_t *buf = janet_string_begin(view.len);
|
||||
for (int32_t i = 0; i < view.len; i++) {
|
||||
uint8_t c = view.bytes[i];
|
||||
if (c >= 97 && c <= 122) {
|
||||
buf[i] = c - 32;
|
||||
} else {
|
||||
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) {
|
||||
const uint8_t *str;
|
||||
uint8_t *buf;
|
||||
int32_t len, i, j;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_BYTES(str, len, args, 0);
|
||||
buf = janet_string_begin(len);
|
||||
for (i = 0, j = len - 1; i < len; i++, j--) {
|
||||
buf[i] = str[j];
|
||||
static Janet cfun_reverse(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetByteView view = janet_getbytes(argv, 0);
|
||||
uint8_t *buf = janet_string_begin(view.len);
|
||||
int32_t i, j;
|
||||
for (i = 0, j = view.len - 1; i < view.len; i++, j--) {
|
||||
buf[i] = view.bytes[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) {
|
||||
const uint8_t *text, *pat;
|
||||
int32_t textlen, patlen, start;
|
||||
JANET_MINARITY(args, 2);
|
||||
JANET_MAXARITY(args, 3 + extra);
|
||||
JANET_ARG_BYTES(pat, patlen, args, 0);
|
||||
JANET_ARG_BYTES(text, textlen, args, 1);
|
||||
if (args.n >= 3) {
|
||||
JANET_ARG_INTEGER(start, args, 2);
|
||||
if (start < 0) {
|
||||
JANET_THROW(args, "expected non-negative start index");
|
||||
}
|
||||
} else {
|
||||
start = 0;
|
||||
static void findsetup(int32_t argc, Janet *argv, struct kmp_state *s, int32_t extra) {
|
||||
janet_arity(argc, 2, 3 + extra);
|
||||
JanetByteView pat = janet_getbytes(argv, 0);
|
||||
JanetByteView text = janet_getbytes(argv, 1);
|
||||
int32_t start = 0;
|
||||
if (argc >= 3) {
|
||||
start = janet_getinteger(argv, 2);
|
||||
if (start < 0) janet_panic("expected non-negative start index");
|
||||
}
|
||||
kmp_init(s, text, textlen, pat, patlen);
|
||||
kmp_init(s, text.bytes, text.len, pat.bytes, pat.len);
|
||||
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;
|
||||
struct kmp_state state;
|
||||
int status = findsetup(args, &state, 0);
|
||||
if (status) return status;
|
||||
findsetup(argc, argv, &state, 0);
|
||||
result = kmp_next(&state);
|
||||
kmp_deinit(&state);
|
||||
JANET_RETURN(args, result < 0
|
||||
? janet_wrap_nil()
|
||||
: janet_wrap_integer(result));
|
||||
return result < 0
|
||||
? janet_wrap_nil()
|
||||
: janet_wrap_integer(result);
|
||||
}
|
||||
|
||||
static int cfun_findall(JanetArgs args) {
|
||||
static Janet cfun_findall(int32_t argc, Janet *argv) {
|
||||
int32_t result;
|
||||
JanetArray *array;
|
||||
struct kmp_state state;
|
||||
int status = findsetup(args, &state, 0);
|
||||
if (status) return status;
|
||||
array = janet_array(0);
|
||||
findsetup(argc, argv, &state, 0);
|
||||
JanetArray *array = janet_array(0);
|
||||
while ((result = kmp_next(&state)) >= 0) {
|
||||
janet_array_push(array, janet_wrap_integer(result));
|
||||
}
|
||||
kmp_deinit(&state);
|
||||
JANET_RETURN_ARRAY(args, array);
|
||||
return janet_wrap_array(array);
|
||||
}
|
||||
|
||||
struct replace_state {
|
||||
@ -1012,39 +952,31 @@ struct replace_state {
|
||||
int32_t substlen;
|
||||
};
|
||||
|
||||
static int replacesetup(JanetArgs args, struct replace_state *s) {
|
||||
const uint8_t *text, *pat, *subst;
|
||||
int32_t textlen, patlen, substlen, start;
|
||||
JANET_MINARITY(args, 3);
|
||||
JANET_MAXARITY(args, 4);
|
||||
JANET_ARG_BYTES(pat, patlen, args, 0);
|
||||
JANET_ARG_BYTES(subst, substlen, args, 1);
|
||||
JANET_ARG_BYTES(text, textlen, args, 2);
|
||||
if (args.n == 4) {
|
||||
JANET_ARG_INTEGER(start, args, 3);
|
||||
if (start < 0) {
|
||||
JANET_THROW(args, "expected non-negative start index");
|
||||
}
|
||||
} else {
|
||||
start = 0;
|
||||
static void replacesetup(int32_t argc, Janet *argv, struct replace_state *s) {
|
||||
janet_arity(argc, 3, 4);
|
||||
JanetByteView pat = janet_getbytes(argv, 0);
|
||||
JanetByteView subst = janet_getbytes(argv, 1);
|
||||
JanetByteView text = janet_getbytes(argv, 2);
|
||||
int32_t start = 0;
|
||||
if (argc == 4) {
|
||||
start = janet_getinteger(argv, 3);
|
||||
if (start < 0) janet_panic("expected non-negative start index");
|
||||
}
|
||||
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->subst = subst;
|
||||
s->substlen = substlen;
|
||||
return JANET_SIGNAL_OK;
|
||||
s->subst = subst.bytes;
|
||||
s->substlen = subst.len;
|
||||
}
|
||||
|
||||
static int cfun_replace(JanetArgs args) {
|
||||
static Janet cfun_replace(int32_t argc, Janet *argv) {
|
||||
int32_t result;
|
||||
struct replace_state s;
|
||||
uint8_t *buf;
|
||||
int status = replacesetup(args, &s);
|
||||
if (status) return status;
|
||||
replacesetup(argc, argv, &s);
|
||||
result = kmp_next(&s.kmp);
|
||||
if (result < 0) {
|
||||
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);
|
||||
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.textlen - result - s.kmp.patlen);
|
||||
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;
|
||||
struct replace_state s;
|
||||
JanetBuffer b;
|
||||
const uint8_t *ret;
|
||||
int32_t lastindex = 0;
|
||||
int status = replacesetup(args, &s);
|
||||
if (status) return status;
|
||||
replacesetup(argc, argv, &s);
|
||||
janet_buffer_init(&b, s.kmp.textlen);
|
||||
while ((result = kmp_next(&s.kmp)) >= 0) {
|
||||
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);
|
||||
}
|
||||
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);
|
||||
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;
|
||||
JanetArray *array;
|
||||
struct kmp_state state;
|
||||
int32_t limit = -1, lastindex = 0;
|
||||
if (args.n == 4) {
|
||||
JANET_ARG_INTEGER(limit, args, 3);
|
||||
if (argc == 4) {
|
||||
limit = janet_getinteger(argv, 3);
|
||||
}
|
||||
int status = findsetup(args, &state, 1);
|
||||
if (status) return status;
|
||||
findsetup(argc, argv, &state, 1);
|
||||
array = janet_array(0);
|
||||
while ((result = kmp_next(&state)) >= 0 && limit--) {
|
||||
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));
|
||||
}
|
||||
kmp_deinit(&state);
|
||||
JANET_RETURN_ARRAY(args, array);
|
||||
return janet_wrap_array(array);
|
||||
}
|
||||
|
||||
static int cfun_checkset(JanetArgs args) {
|
||||
const uint8_t *set, *str;
|
||||
int32_t setlen, strlen, i;
|
||||
static Janet cfun_checkset(int32_t argc, Janet *argv) {
|
||||
uint32_t bitset[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
JANET_MINARITY(args, 2);
|
||||
JANET_MAXARITY(args, 3);
|
||||
JANET_ARG_BYTES(set, setlen, args, 0);
|
||||
JANET_ARG_BYTES(str, strlen, args, 1);
|
||||
janet_arity(argc, 2, 3);
|
||||
JanetByteView set = janet_getbytes(argv, 0);
|
||||
JanetByteView str = janet_getbytes(argv, 1);
|
||||
/* Populate set */
|
||||
for (i = 0; i < setlen; i++) {
|
||||
int index = set[i] >> 5;
|
||||
uint32_t mask = 1 << (set[i] & 7);
|
||||
for (int32_t i = 0; i < set.len; i++) {
|
||||
int index = set.bytes[i] >> 5;
|
||||
uint32_t mask = 1 << (set.bytes[i] & 7);
|
||||
bitset[index] |= mask;
|
||||
}
|
||||
if (args.n == 3) {
|
||||
int invert;
|
||||
JANET_ARG_BOOLEAN(invert, args, 2);
|
||||
if (invert) {
|
||||
for (i = 0; i < 8; i++)
|
||||
if (argc == 3) {
|
||||
if (janet_getboolean(argv, 2)) {
|
||||
for (int i = 0; i < 8; i++)
|
||||
bitset[i] = ~bitset[i];
|
||||
}
|
||||
}
|
||||
/* Check set */
|
||||
for (i = 0; i < strlen; i++) {
|
||||
int index = str[i] >> 5;
|
||||
uint32_t mask = 1 << (str[i] & 7);
|
||||
for (int32_t i = 0; i < str.len; i++) {
|
||||
int index = str.bytes[i] >> 5;
|
||||
uint32_t mask = 1 << (str.bytes[i] & 7);
|
||||
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) {
|
||||
const Janet *parts;
|
||||
const uint8_t *joiner;
|
||||
uint8_t *buf, *out;
|
||||
int32_t joinerlen, partslen, finallen, i;
|
||||
JANET_MINARITY(args, 1);
|
||||
JANET_MAXARITY(args, 2);
|
||||
JANET_ARG_INDEXED(parts, partslen, args, 0);
|
||||
if (args.n == 2) {
|
||||
JANET_ARG_BYTES(joiner, joinerlen, args, 1);
|
||||
static Janet cfun_join(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 2);
|
||||
JanetView parts = janet_getindexed(argv, 0);
|
||||
JanetByteView joiner;
|
||||
if (argc == 2) {
|
||||
joiner = janet_getbytes(argv, 1);
|
||||
} else {
|
||||
joiner = NULL;
|
||||
joinerlen = 0;
|
||||
joiner.bytes = NULL;
|
||||
joiner.len = 0;
|
||||
}
|
||||
/* Check args */
|
||||
finallen = 0;
|
||||
for (i = 0; i < partslen; i++) {
|
||||
int32_t i;
|
||||
int64_t finallen = 0;
|
||||
for (i = 0; i < parts.len; i++) {
|
||||
const uint8_t *chunk;
|
||||
int32_t chunklen = 0;
|
||||
if (!janet_bytes_view(parts[i], &chunk, &chunklen)) {
|
||||
JANET_THROW(args, "expected string|symbol|buffer");
|
||||
if (!janet_bytes_view(parts.items[i], &chunk, &chunklen)) {
|
||||
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;
|
||||
if (finallen > INT32_MAX)
|
||||
janet_panic("result string too long");
|
||||
}
|
||||
uint8_t *buf, *out;
|
||||
out = buf = janet_string_begin(finallen);
|
||||
for (i = 0; i < partslen; i++) {
|
||||
for (i = 0; i < parts.len; i++) {
|
||||
const uint8_t *chunk = NULL;
|
||||
int32_t chunklen = 0;
|
||||
if (i) {
|
||||
memcpy(out, joiner, joinerlen);
|
||||
out += joinerlen;
|
||||
memcpy(out, joiner.bytes, joiner.len);
|
||||
out += joiner.len;
|
||||
}
|
||||
janet_bytes_view(parts[i], &chunk, &chunklen);
|
||||
janet_bytes_view(parts.items[i], &chunk, &chunklen);
|
||||
memcpy(out, chunk, chunklen);
|
||||
out += chunklen;
|
||||
}
|
||||
JANET_RETURN_STRING(args, janet_string_end(buf));
|
||||
return janet_wrap_string(janet_string_end(buf));
|
||||
}
|
||||
|
||||
static struct formatter {
|
||||
@ -1188,29 +1112,29 @@ static struct formatter {
|
||||
{"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];
|
||||
char buf[100];
|
||||
double x;
|
||||
int formatNargs = 1;
|
||||
int32_t precision = 0;
|
||||
JANET_MINARITY(args, 1);
|
||||
JANET_MAXARITY(args, 4);
|
||||
JANET_ARG_NUMBER(x, args, 0);
|
||||
if (args.n >= 2) {
|
||||
const uint8_t *flag;
|
||||
JANET_ARG_KEYWORD(flag, args, 1);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (argc >= 2) {
|
||||
const uint8_t *flag = janet_getkeyword(argv, 1);
|
||||
int i;
|
||||
for (i = 0; i < 6; i++) {
|
||||
struct formatter fmttest = formatters[i];
|
||||
if (!janet_cstrcmp(flag, fmttest.lead)) {
|
||||
fmter = fmttest;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 6)
|
||||
janet_panicf("unsupported formatter %v", argv[1]);
|
||||
}
|
||||
|
||||
if (args.n >= 3) {
|
||||
JANET_ARG_INTEGER(precision, args, 2);
|
||||
if (argc >= 3) {
|
||||
precision = janet_getinteger(argv, 2);
|
||||
formatNargs++;
|
||||
}
|
||||
|
||||
@ -1220,20 +1144,19 @@ static int cfun_number(JanetArgs args) {
|
||||
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;
|
||||
int32_t depth = 4;
|
||||
JANET_MINARITY(args, 1);
|
||||
JANET_MAXARITY(args, 3);
|
||||
if (args.n > 1)
|
||||
JANET_ARG_INTEGER(depth, args, 1);
|
||||
if (args.n > 2)
|
||||
JANET_ARG_BUFFER(buffer, args, 2);
|
||||
buffer = janet_pretty(buffer, depth, args.v[0]);
|
||||
JANET_RETURN_BUFFER(args, buffer);
|
||||
if (argc > 1)
|
||||
depth = janet_getinteger(argv, 1);
|
||||
if (argc > 2)
|
||||
buffer = janet_getbuffer(argv, 2);
|
||||
buffer = janet_pretty(buffer, depth, argv[0]);
|
||||
return janet_wrap_buffer(buffer);
|
||||
}
|
||||
|
||||
static const JanetReg cfuns[] = {
|
||||
@ -1337,8 +1260,6 @@ static const JanetReg cfuns[] = {
|
||||
};
|
||||
|
||||
/* Module entry point */
|
||||
int janet_lib_string(JanetArgs args) {
|
||||
JanetTable *env = janet_env(args);
|
||||
void janet_lib_string(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, cfuns);
|
||||
return 0;
|
||||
}
|
||||
|
@ -163,8 +163,7 @@ const JanetKV *janet_table_next(JanetTable *t, const JanetKV *kv) {
|
||||
JanetKV *end = t->data + t->capacity;
|
||||
kv = (kv == NULL) ? t->data : kv + 1;
|
||||
while (kv < end) {
|
||||
if (!janet_checktype(kv->key, JANET_NIL))
|
||||
return kv;
|
||||
if (!janet_checktype(kv->key, JANET_NIL)) return kv;
|
||||
kv++;
|
||||
}
|
||||
return NULL;
|
||||
@ -206,49 +205,41 @@ void janet_table_merge_struct(JanetTable *table, const JanetKV *other) {
|
||||
|
||||
/* C Functions */
|
||||
|
||||
static int cfun_new(JanetArgs args) {
|
||||
JanetTable *t;
|
||||
int32_t cap;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_INTEGER(cap, args, 0);
|
||||
t = janet_table(cap);
|
||||
JANET_RETURN_TABLE(args, t);
|
||||
static Janet cfun_new(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
int32_t cap = janet_getinteger(argv, 0);
|
||||
return janet_wrap_table(janet_table(cap));
|
||||
}
|
||||
|
||||
static int cfun_getproto(JanetArgs args) {
|
||||
JanetTable *t;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_TABLE(t, args, 0);
|
||||
JANET_RETURN(args, t->proto
|
||||
? janet_wrap_table(t->proto)
|
||||
: janet_wrap_nil());
|
||||
static Janet cfun_getproto(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetTable *t = janet_gettable(argv, 0);
|
||||
return t->proto
|
||||
? janet_wrap_table(t->proto)
|
||||
: janet_wrap_nil();
|
||||
}
|
||||
|
||||
static int cfun_setproto(JanetArgs args) {
|
||||
JanetTable *table, *proto;
|
||||
JANET_FIXARITY(args, 2);
|
||||
JANET_ARG_TABLE(table, args, 0);
|
||||
if (janet_checktype(args.v[1], JANET_NIL)) {
|
||||
proto = NULL;
|
||||
} else {
|
||||
JANET_ARG_TABLE(proto, args, 1);
|
||||
static Janet cfun_setproto(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 2, 2);
|
||||
JanetTable *table = janet_gettable(argv, 0);
|
||||
JanetTable *proto = NULL;
|
||||
if (!janet_checktype(argv[1], JANET_NIL)) {
|
||||
proto = janet_gettable(argv, 1);
|
||||
}
|
||||
table->proto = proto;
|
||||
JANET_RETURN_TABLE(args, table);
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static int cfun_tostruct(JanetArgs args) {
|
||||
JanetTable *t;
|
||||
JANET_FIXARITY(args, 1);
|
||||
JANET_ARG_TABLE(t, args, 0);
|
||||
JANET_RETURN_STRUCT(args, janet_table_to_struct(t));
|
||||
static Janet cfun_tostruct(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 1);
|
||||
JanetTable *t = janet_gettable(argv, 0);
|
||||
return janet_wrap_struct(janet_table_to_struct(t));
|
||||
}
|
||||
|
||||
static int cfun_rawget(JanetArgs args) {
|
||||
JanetTable *table;
|
||||
JANET_FIXARITY(args, 2);
|
||||
JANET_ARG_TABLE(table, args, 0);
|
||||
JANET_RETURN(args, janet_table_rawget(table, args.v[1]));
|
||||
static Janet cfun_rawget(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 2, 2);
|
||||
JanetTable *table = janet_gettable(argv, 0);
|
||||
return janet_table_rawget(table, argv[1]);
|
||||
}
|
||||
|
||||
static const JanetReg cfuns[] = {
|
||||
@ -283,10 +274,6 @@ static const JanetReg cfuns[] = {
|
||||
};
|
||||
|
||||
/* Load the table module */
|
||||
int janet_lib_table(JanetArgs args) {
|
||||
JanetTable *env = janet_env(args);
|
||||
void janet_lib_table(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, cfuns);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef janet_maphash
|
||||
|
@ -91,64 +91,30 @@ int janet_tuple_compare(const Janet *lhs, const Janet *rhs) {
|
||||
|
||||
/* C Functions */
|
||||
|
||||
static int cfun_slice(JanetArgs args) {
|
||||
const Janet *vals;
|
||||
int32_t len;
|
||||
Janet *ret;
|
||||
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 Janet cfun_slice(int32_t argc, Janet *argv) {
|
||||
JanetRange range = janet_getslice(argc, argv);
|
||||
JanetView view = janet_getindexed(argv, 0);
|
||||
return janet_wrap_tuple(janet_tuple_n(view.items + range.start, range.end - range.start));
|
||||
}
|
||||
|
||||
static int cfun_prepend(JanetArgs args) {
|
||||
const Janet *t;
|
||||
int32_t len, i;
|
||||
Janet *n;
|
||||
JANET_MINARITY(args, 1);
|
||||
if (!janet_indexed_view(args.v[0], &t, &len))
|
||||
JANET_THROW(args, "expected tuple/array");
|
||||
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];
|
||||
static Janet cfun_prepend(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, -1);
|
||||
JanetView view = janet_getindexed(argv, 0);
|
||||
Janet *n = janet_tuple_begin(view.len - 1 + argc);
|
||||
memcpy(n - 1 + argc, view.items, sizeof(Janet) * view.len);
|
||||
for (int32_t i = 1; i < argc; i++) {
|
||||
n[argc - i - 1] = argv[i];
|
||||
}
|
||||
JANET_RETURN_TUPLE(args, janet_tuple_end(n));
|
||||
return janet_wrap_tuple(janet_tuple_end(n));
|
||||
}
|
||||
|
||||
static int cfun_append(JanetArgs args) {
|
||||
const Janet *t;
|
||||
int32_t len;
|
||||
Janet *n;
|
||||
JANET_MINARITY(args, 1);
|
||||
if (!janet_indexed_view(args.v[0], &t, &len))
|
||||
JANET_THROW(args, "expected tuple/array");
|
||||
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 Janet cfun_append(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, -1);
|
||||
JanetView view = janet_getindexed(argv, 0);
|
||||
Janet *n = janet_tuple_begin(view.len - 1 + argc);
|
||||
memcpy(n, view.items, sizeof(Janet) * view.len);
|
||||
memcpy(n + view.len, argv + 1, sizeof(Janet) * (argc - 1));
|
||||
return janet_wrap_tuple(janet_tuple_end(n));
|
||||
}
|
||||
|
||||
static const JanetReg cfuns[] = {
|
||||
@ -174,8 +140,6 @@ static const JanetReg cfuns[] = {
|
||||
};
|
||||
|
||||
/* Load the tuple module */
|
||||
int janet_lib_tuple(JanetArgs args) {
|
||||
JanetTable *env = janet_env(args);
|
||||
void janet_lib_tuple(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, cfuns);
|
||||
return 0;
|
||||
}
|
||||
|
@ -304,18 +304,6 @@ JanetBindingType janet_resolve(JanetTable *env, const uint8_t *sym, Janet *out)
|
||||
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
|
||||
* view can be constructed, 0 if an invalid type. */
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
if (!janet_checktype(x, JANET_NUMBER))
|
||||
return 0;
|
||||
|
@ -44,21 +44,21 @@ const void *janet_strbinsearch(
|
||||
const uint8_t *key);
|
||||
|
||||
/* Initialize builtin libraries */
|
||||
int janet_lib_io(JanetArgs args);
|
||||
int janet_lib_math(JanetArgs args);
|
||||
int janet_lib_array(JanetArgs args);
|
||||
int janet_lib_tuple(JanetArgs args);
|
||||
int janet_lib_buffer(JanetArgs args);
|
||||
int janet_lib_table(JanetArgs args);
|
||||
int janet_lib_fiber(JanetArgs args);
|
||||
int janet_lib_os(JanetArgs args);
|
||||
int janet_lib_string(JanetArgs args);
|
||||
int janet_lib_marsh(JanetArgs args);
|
||||
int janet_lib_parse(JanetArgs args);
|
||||
void janet_lib_io(JanetTable *env);
|
||||
void janet_lib_math(JanetTable *env);
|
||||
void janet_lib_array(JanetTable *env);
|
||||
void janet_lib_tuple(JanetTable *env);
|
||||
void janet_lib_buffer(JanetTable *env);
|
||||
void janet_lib_table(JanetTable *env);
|
||||
void janet_lib_fiber(JanetTable *env);
|
||||
void janet_lib_os(JanetTable *env);
|
||||
void janet_lib_string(JanetTable *env);
|
||||
void janet_lib_marsh(JanetTable *env);
|
||||
void janet_lib_parse(JanetTable *env);
|
||||
#ifdef JANET_ASSEMBLER
|
||||
int janet_lib_asm(JanetArgs args);
|
||||
void janet_lib_asm(JanetTable *env);
|
||||
#endif
|
||||
int janet_lib_compile(JanetArgs args);
|
||||
int janet_lib_debug(JanetArgs args);
|
||||
void janet_lib_compile(JanetTable *env);
|
||||
void janet_lib_debug(JanetTable *env);
|
||||
|
||||
#endif
|
||||
|
@ -572,18 +572,14 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
||||
pc = func->def->bytecode;
|
||||
vm_checkgc_next();
|
||||
} else if (janet_checktype(callee, JANET_CFUNCTION)) {
|
||||
JanetArgs args;
|
||||
Janet retreg = janet_wrap_nil();
|
||||
vm_commit();
|
||||
args.n = fiber->stacktop - fiber->stackstart;
|
||||
int32_t argc = fiber->stacktop - fiber->stackstart;
|
||||
janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee));
|
||||
args.v = fiber->data + fiber->frame;
|
||||
args.ret = &retreg;
|
||||
if (janet_unwrap_cfunction(callee)(args)) janet_panicv(retreg);
|
||||
Janet ret = janet_unwrap_cfunction(callee)(argc, fiber->data + fiber->frame);
|
||||
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[A] = retreg;
|
||||
stack[A] = ret;
|
||||
vm_checkgc_pcnext();
|
||||
} else {
|
||||
vm_commit();
|
||||
@ -606,19 +602,14 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
||||
pc = func->def->bytecode;
|
||||
vm_checkgc_next();
|
||||
} else {
|
||||
Janet retreg = janet_wrap_nil();
|
||||
Janet retreg;
|
||||
vm_commit();
|
||||
if (janet_checktype(callee, JANET_CFUNCTION)) {
|
||||
JanetArgs args;
|
||||
vm_commit();
|
||||
args.n = fiber->stacktop - fiber->stackstart;
|
||||
int32_t argc = fiber->stacktop - fiber->stackstart;
|
||||
janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee));
|
||||
args.v = fiber->data + fiber->frame;
|
||||
args.ret = &retreg;
|
||||
if (janet_unwrap_cfunction(callee)(args))
|
||||
vm_return(JANET_SIGNAL_ERROR, retreg);
|
||||
retreg = janet_unwrap_cfunction(callee)(argc, fiber->data + fiber->frame);
|
||||
janet_fiber_popframe(fiber);
|
||||
} else {
|
||||
vm_commit();
|
||||
retreg = call_nonfn(fiber, callee);
|
||||
}
|
||||
janet_fiber_popframe(fiber);
|
||||
@ -653,22 +644,27 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
||||
}
|
||||
|
||||
VM_OP(JOP_PUT)
|
||||
vm_commit();
|
||||
janet_put(stack[A], stack[B], stack[C]);
|
||||
vm_checkgc_pcnext();
|
||||
|
||||
VM_OP(JOP_PUT_INDEX)
|
||||
vm_commit();
|
||||
janet_putindex(stack[A], C, stack[B]);
|
||||
vm_checkgc_pcnext();
|
||||
|
||||
VM_OP(JOP_GET)
|
||||
vm_commit();
|
||||
stack[A] = janet_get(stack[B], stack[C]);
|
||||
vm_pcnext();
|
||||
|
||||
VM_OP(JOP_GET_INDEX)
|
||||
vm_commit();
|
||||
stack[A] = janet_getindex(stack[B], C);
|
||||
vm_pcnext();
|
||||
|
||||
VM_OP(JOP_LENGTH)
|
||||
vm_commit();
|
||||
stack[A] = janet_wrap_integer(janet_length(stack[E]));
|
||||
vm_pcnext();
|
||||
|
||||
|
@ -268,10 +268,13 @@ typedef struct JanetFuncEnv JanetFuncEnv;
|
||||
typedef struct JanetKV JanetKV;
|
||||
typedef struct JanetStackFrame JanetStackFrame;
|
||||
typedef struct JanetAbstractType JanetAbstractType;
|
||||
typedef struct JanetArgs JanetArgs;
|
||||
typedef struct JanetReg JanetReg;
|
||||
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 */
|
||||
typedef enum JanetType {
|
||||
@ -573,13 +576,6 @@ JANET_API int janet_checkint64(Janet x);
|
||||
|
||||
#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. */
|
||||
#define JANET_FIBER_MASK_ERROR 2
|
||||
#define JANET_FIBER_MASK_DEBUG 4
|
||||
@ -760,6 +756,27 @@ struct JanetReg {
|
||||
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 *****/
|
||||
|
||||
/***** 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);
|
||||
|
||||
/* Debugging */
|
||||
JANET_API int janet_debug_break(JanetFuncDef *def, int32_t pc);
|
||||
JANET_API int janet_debug_unbreak(JanetFuncDef *def, int32_t pc);
|
||||
JANET_API int janet_debug_find(
|
||||
JANET_API void janet_debug_break(JanetFuncDef *def, int32_t pc);
|
||||
JANET_API void janet_debug_unbreak(JanetFuncDef *def, int32_t pc);
|
||||
JANET_API void janet_debug_find(
|
||||
JanetFuncDef **def_out, int32_t *pc_out,
|
||||
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_ensure(JanetBuffer *buffer, int32_t capacity, int32_t growth);
|
||||
JANET_API void janet_buffer_setcount(JanetBuffer *buffer, int32_t count);
|
||||
JANET_API int 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 int janet_buffer_push_string(JanetBuffer *buffer, const uint8_t *string);
|
||||
JANET_API int janet_buffer_push_cstring(JanetBuffer *buffer, const char *cstring);
|
||||
JANET_API int janet_buffer_push_u8(JanetBuffer *buffer, uint8_t x);
|
||||
JANET_API int janet_buffer_push_u16(JanetBuffer *buffer, uint16_t x);
|
||||
JANET_API int 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_extra(JanetBuffer *buffer, int32_t n);
|
||||
JANET_API void janet_buffer_push_bytes(JanetBuffer *buffer, const uint8_t *string, int32_t len);
|
||||
JANET_API void janet_buffer_push_string(JanetBuffer *buffer, const uint8_t *string);
|
||||
JANET_API void janet_buffer_push_cstring(JanetBuffer *buffer, const char *cstring);
|
||||
JANET_API void janet_buffer_push_u8(JanetBuffer *buffer, uint8_t x);
|
||||
JANET_API void janet_buffer_push_u16(JanetBuffer *buffer, uint16_t x);
|
||||
JANET_API void janet_buffer_push_u32(JanetBuffer *buffer, uint32_t x);
|
||||
JANET_API void janet_buffer_push_u64(JanetBuffer *buffer, uint64_t x);
|
||||
|
||||
/* Tuple */
|
||||
#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);
|
||||
|
||||
/* 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 */
|
||||
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_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cfuns);
|
||||
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);
|
||||
|
||||
/* 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 */
|
||||
|
||||
#define JANET_MODULE_ENTRY JANET_API void _janet_init
|
||||
JANET_API void janet_panicv(Janet message);
|
||||
JANET_API void janet_panic(const char *message);
|
||||
JANET_API void janet_panics(const uint8_t *message);
|
||||
#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_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 */
|
||||
#define JANET_MODULE_ENTRY JANET_API int _janet_init
|
||||
JANET_API double janet_getnumber(const Janet *argv, int32_t n);
|
||||
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 *****/
|
||||
|
||||
/***** 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
|
||||
}
|
||||
#endif
|
||||
|
@ -23,14 +23,12 @@
|
||||
#include "line.h"
|
||||
|
||||
/* Common */
|
||||
int janet_line_getter(JanetArgs args) {
|
||||
JANET_FIXARITY(args, 2);
|
||||
JANET_CHECK(args, 0, JANET_STRING);
|
||||
JANET_CHECK(args, 1, JANET_BUFFER);
|
||||
janet_line_get(
|
||||
janet_unwrap_string(args.v[0]),
|
||||
janet_unwrap_buffer(args.v[1]));
|
||||
JANET_RETURN(args, args.v[0]);
|
||||
Janet janet_line_getter(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 2, 2);
|
||||
const uint8_t *str = janet_getstring(argv, 0);
|
||||
JanetBuffer *buf = janet_getbuffer(argv, 1);
|
||||
janet_line_get(str, buf);
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static void simpleline(JanetBuffer *buffer) {
|
||||
|
@ -29,6 +29,6 @@ void janet_line_init();
|
||||
void janet_line_deinit();
|
||||
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user