mirror of
https://github.com/janet-lang/janet
synced 2024-11-25 09:47:17 +00:00
Remove file/fileno and file/fdopen.
Also fully add call function pointer to abstract types, including in methods, etc.
This commit is contained in:
parent
4fad0714e7
commit
b8d530da36
@ -256,7 +256,7 @@ static Janet cfun_it_##type##_##name(int32_t argc, Janet *argv) { \
|
|||||||
|
|
||||||
#define DIVMETHODINVERT_SIGNED(T, type, name, oper) \
|
#define DIVMETHODINVERT_SIGNED(T, type, name, oper) \
|
||||||
static Janet cfun_it_##type##_##name(int32_t argc, Janet *argv) { \
|
static Janet cfun_it_##type##_##name(int32_t argc, Janet *argv) { \
|
||||||
janet_arity(argc, 2, -1); \
|
janet_fixarity(argc, 2); \
|
||||||
T *box = janet_abstract(&it_##type##_type, sizeof(T)); \
|
T *box = janet_abstract(&it_##type##_type, sizeof(T)); \
|
||||||
*box = janet_unwrap_##type(argv[1]); \
|
*box = janet_unwrap_##type(argv[1]); \
|
||||||
T value = janet_unwrap_##type(argv[0]); \
|
T value = janet_unwrap_##type(argv[0]); \
|
||||||
|
@ -157,36 +157,6 @@ static Janet cfun_io_fopen(int32_t argc, Janet *argv) {
|
|||||||
return f ? makef(f, flags) : janet_wrap_nil();
|
return f ? makef(f, flags) : janet_wrap_nil();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Janet cfun_io_fdopen(int32_t argc, Janet *argv) {
|
|
||||||
janet_arity(argc, 1, 2);
|
|
||||||
const int fd = janet_getinteger(argv, 0);
|
|
||||||
const uint8_t *fmode;
|
|
||||||
int flags;
|
|
||||||
if (argc == 2) {
|
|
||||||
fmode = janet_getkeyword(argv, 1);
|
|
||||||
flags = checkflags(fmode);
|
|
||||||
} else {
|
|
||||||
fmode = (const uint8_t *)"r";
|
|
||||||
flags = JANET_FILE_READ;
|
|
||||||
}
|
|
||||||
#ifdef JANET_WINDOWS
|
|
||||||
#define fdopen _fdopen
|
|
||||||
#endif
|
|
||||||
FILE *f = fdopen(fd, (const char *)fmode);
|
|
||||||
return f ? makef(f, flags) : janet_wrap_nil();
|
|
||||||
}
|
|
||||||
|
|
||||||
static Janet cfun_io_fileno(int32_t argc, Janet *argv) {
|
|
||||||
janet_fixarity(argc, 1);
|
|
||||||
IOFile *iof = janet_getabstract(argv, 0, &cfun_io_filetype);
|
|
||||||
if (iof->flags & JANET_FILE_CLOSED)
|
|
||||||
janet_panic("file is closed");
|
|
||||||
#ifdef JANET_WINDOWS
|
|
||||||
#define fileno _fileno
|
|
||||||
#endif
|
|
||||||
return janet_wrap_integer(fileno(iof->file));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read up to n bytes into buffer. */
|
/* Read up to n bytes into buffer. */
|
||||||
static void read_chunk(IOFile *iof, JanetBuffer *buffer, int32_t nBytesMax) {
|
static void read_chunk(IOFile *iof, JanetBuffer *buffer, int32_t nBytesMax) {
|
||||||
if (!(iof->flags & (JANET_FILE_READ | JANET_FILE_UPDATE)))
|
if (!(iof->flags & (JANET_FILE_READ | JANET_FILE_UPDATE)))
|
||||||
@ -338,7 +308,6 @@ static Janet cfun_io_fseek(int32_t argc, Janet *argv) {
|
|||||||
|
|
||||||
static JanetMethod io_file_methods[] = {
|
static JanetMethod io_file_methods[] = {
|
||||||
{"close", cfun_io_fclose},
|
{"close", cfun_io_fclose},
|
||||||
{"fileno", cfun_io_fileno},
|
|
||||||
{"flush", cfun_io_fflush},
|
{"flush", cfun_io_fflush},
|
||||||
{"read", cfun_io_fread},
|
{"read", cfun_io_fread},
|
||||||
{"seek", cfun_io_fseek},
|
{"seek", cfun_io_fseek},
|
||||||
@ -592,26 +561,6 @@ static const JanetReg io_cfuns[] = {
|
|||||||
"\tb - open the file in binary mode (rather than text mode)\n"
|
"\tb - open the file in binary mode (rather than text mode)\n"
|
||||||
"\t+ - append to the file instead of overwriting it")
|
"\t+ - append to the file instead of overwriting it")
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"file/fdopen", cfun_io_fdopen,
|
|
||||||
JDOC("(file/fdopen fd &opt mode)\n\n"
|
|
||||||
"Create a file from an fd. fd is a platform specific file descriptor, and "
|
|
||||||
"mode is a set of flags indicating the mode to open the file in. "
|
|
||||||
"mode is a keyword where each character represents a flag. If the file "
|
|
||||||
"cannot be opened, returns nil, otherwise returns the new file handle. "
|
|
||||||
"Mode flags:\n\n"
|
|
||||||
"\tr - allow reading from the file\n"
|
|
||||||
"\tw - allow writing to the file\n"
|
|
||||||
"\ta - append to the file\n"
|
|
||||||
"\tb - open the file in binary mode (rather than text mode)\n"
|
|
||||||
"\t+ - append to the file instead of overwriting it")
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"file/fileno", cfun_io_fileno,
|
|
||||||
JDOC("(file/fileno f)\n\n"
|
|
||||||
"Return the underlying file descriptor for the file as a number."
|
|
||||||
"The meaning of this number is platform specific.")
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"file/close", cfun_io_fclose,
|
"file/close", cfun_io_fclose,
|
||||||
JDOC("(file/close f)\n\n"
|
JDOC("(file/close f)\n\n"
|
||||||
|
121
src/core/vm.c
121
src/core/vm.c
@ -195,49 +195,64 @@ JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf = NULL;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Trace a function call */
|
/* Trace a function call */
|
||||||
static void vm_do_trace(JanetFunction *func) {
|
static void vm_do_trace(JanetFunction *func, int32_t argc, const Janet *argv) {
|
||||||
Janet *stack = janet_vm_fiber->data + janet_vm_fiber->stackstart;
|
if (func->def->name){
|
||||||
int32_t start = janet_vm_fiber->stackstart;
|
|
||||||
int32_t end = janet_vm_fiber->stacktop;
|
|
||||||
int32_t argc = end - start;
|
|
||||||
if (func->def->name) {
|
|
||||||
janet_printf("trace (%S", func->def->name);
|
janet_printf("trace (%S", func->def->name);
|
||||||
} else {
|
} else {
|
||||||
janet_printf("trace (%p", janet_wrap_function(func));
|
janet_printf("trace (%p", janet_wrap_function(func));
|
||||||
}
|
}
|
||||||
for (int32_t i = 0; i < argc; i++) {
|
for (int32_t i = 0; i < argc; i++) {
|
||||||
janet_printf(" %p", stack[i]);
|
janet_printf(" %p", argv[i]);
|
||||||
}
|
}
|
||||||
printf(")\n");
|
janet_printf(")\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call a non function type */
|
/* Invoke a method once we have looked it up */
|
||||||
static Janet call_nonfn(JanetFiber *fiber, Janet callee) {
|
static Janet janet_method_invoke(Janet method, int32_t argc, Janet *argv) {
|
||||||
int32_t argn = fiber->stacktop - fiber->stackstart;
|
switch (janet_type(method)) {
|
||||||
Janet ds, key;
|
case JANET_CFUNCTION:
|
||||||
JanetType t = janet_type(callee);
|
return (janet_unwrap_cfunction(method))(argc, argv);
|
||||||
if (t == JANET_ABSTRACT) {
|
case JANET_FUNCTION: {
|
||||||
JanetAbstract abst = janet_unwrap_abstract(callee);
|
JanetFunction *fun = janet_unwrap_function(method);
|
||||||
const JanetAbstractType *at = janet_abstract_type(abst);
|
return janet_call(fun, argc, argv);
|
||||||
if (NULL != at->call) {
|
}
|
||||||
fiber->stacktop = fiber->stackstart;
|
case JANET_ABSTRACT: {
|
||||||
return at->call(abst, argn, fiber->data + fiber->stackstart);
|
JanetAbstract abst = janet_unwrap_abstract(method);
|
||||||
|
const JanetAbstractType *at = janet_abstract_type(abst);
|
||||||
|
if (NULL != at->call) {
|
||||||
|
return at->call(abst, argc, argv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* fallthrough */
|
||||||
|
case JANET_STRING:
|
||||||
|
case JANET_BUFFER:
|
||||||
|
case JANET_TABLE:
|
||||||
|
case JANET_STRUCT:
|
||||||
|
case JANET_ARRAY:
|
||||||
|
case JANET_TUPLE: {
|
||||||
|
if (argc != 1) {
|
||||||
|
janet_panicf("%v called with %d arguments, possibly expected 1", method, argc);
|
||||||
|
}
|
||||||
|
return janet_in(method, argv[0]);
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
if (argc != 1) {
|
||||||
|
janet_panicf("%v called with %d arguments, possibly expected 1", method, argc);
|
||||||
|
}
|
||||||
|
return janet_in(argv[0], method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (argn != 1) janet_panicf("%v called with %d arguments, possibly expected 1", callee, argn);
|
|
||||||
if ((1 << t) & (JANET_TFLAG_INDEXED | JANET_TFLAG_DICTIONARY |
|
|
||||||
JANET_TFLAG_STRING | JANET_TFLAG_BUFFER | JANET_TFLAG_ABSTRACT)) {
|
|
||||||
ds = callee;
|
|
||||||
key = fiber->data[fiber->stackstart];
|
|
||||||
} else {
|
|
||||||
ds = fiber->data[fiber->stackstart];
|
|
||||||
key = callee;
|
|
||||||
}
|
|
||||||
fiber->stacktop = fiber->stackstart;
|
|
||||||
return janet_in(ds, key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a callable from a keyword method name and check ensure that it is valid. */
|
/* Call a non function type from a JOP_CALL or JOP_TAILCALL instruction.
|
||||||
|
* Assumes that the arguments are on the fiber stack. */
|
||||||
|
static Janet call_nonfn(JanetFiber *fiber, Janet callee) {
|
||||||
|
int32_t argc = fiber->stacktop - fiber->stackstart;
|
||||||
|
fiber->stacktop = fiber->stackstart;
|
||||||
|
return janet_method_invoke(callee, argc, fiber->data + fiber->stacktop);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get a callable from a keyword method name and ensure that it is valid. */
|
||||||
static Janet resolve_method(Janet name, JanetFiber *fiber) {
|
static Janet resolve_method(Janet name, JanetFiber *fiber) {
|
||||||
int32_t argc = fiber->stacktop - fiber->stackstart;
|
int32_t argc = fiber->stacktop - fiber->stackstart;
|
||||||
if (argc < 1) janet_panicf("method call (%v) takes at least 1 argument, got 0", name);
|
if (argc < 1) janet_panicf("method call (%v) takes at least 1 argument, got 0", name);
|
||||||
@ -250,36 +265,7 @@ static Janet resolve_method(Janet name, JanetFiber *fiber) {
|
|||||||
/* Lookup method on value x */
|
/* Lookup method on value x */
|
||||||
static Janet janet_method_lookup(Janet x, const char *name) {
|
static Janet janet_method_lookup(Janet x, const char *name) {
|
||||||
Janet kname = janet_ckeywordv(name);
|
Janet kname = janet_ckeywordv(name);
|
||||||
switch (janet_type(x)) {
|
return janet_get(x, kname);
|
||||||
default:
|
|
||||||
return janet_wrap_nil();
|
|
||||||
case JANET_ABSTRACT: {
|
|
||||||
Janet method;
|
|
||||||
void *abst = janet_unwrap_abstract(x);
|
|
||||||
JanetAbstractType *type = (JanetAbstractType *)janet_abstract_type(abst);
|
|
||||||
if (!type->get || !(type->get)(abst, kname, &method)) {
|
|
||||||
return janet_wrap_nil();
|
|
||||||
} else {
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case JANET_TABLE:
|
|
||||||
return janet_table_get(janet_unwrap_table(x), kname);
|
|
||||||
case JANET_STRUCT:
|
|
||||||
return janet_struct_get(janet_unwrap_struct(x), kname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Invoke a method once we have looked it up */
|
|
||||||
static Janet janet_method_invoke(Janet method, int32_t argc, Janet *argv) {
|
|
||||||
if (janet_checktype(method, JANET_CFUNCTION)) {
|
|
||||||
return (janet_unwrap_cfunction(method))(argc, argv);
|
|
||||||
} else if (janet_checktype(method, JANET_FUNCTION)) {
|
|
||||||
JanetFunction *fun = janet_unwrap_function(method);
|
|
||||||
return janet_call(fun, argc, argv);
|
|
||||||
} else {
|
|
||||||
janet_panicf("method is not callable: %v", method);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call a method first on the righthand side, and then on the left hand side with a prefix */
|
/* Call a method first on the righthand side, and then on the left hand side with a prefix */
|
||||||
@ -901,7 +887,9 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
}
|
}
|
||||||
if (janet_checktype(callee, JANET_FUNCTION)) {
|
if (janet_checktype(callee, JANET_FUNCTION)) {
|
||||||
func = janet_unwrap_function(callee);
|
func = janet_unwrap_function(callee);
|
||||||
if (func->gc.flags & JANET_FUNCFLAG_TRACE) vm_do_trace(func);
|
if (func->gc.flags & JANET_FUNCFLAG_TRACE) {
|
||||||
|
vm_do_trace(func, fiber->stacktop - fiber->stackstart, stack);
|
||||||
|
}
|
||||||
janet_stack_frame(stack)->pc = pc;
|
janet_stack_frame(stack)->pc = pc;
|
||||||
if (janet_fiber_funcframe(fiber, func)) {
|
if (janet_fiber_funcframe(fiber, func)) {
|
||||||
int32_t n = fiber->stacktop - fiber->stackstart;
|
int32_t n = fiber->stacktop - fiber->stackstart;
|
||||||
@ -938,7 +926,9 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
}
|
}
|
||||||
if (janet_checktype(callee, JANET_FUNCTION)) {
|
if (janet_checktype(callee, JANET_FUNCTION)) {
|
||||||
func = janet_unwrap_function(callee);
|
func = janet_unwrap_function(callee);
|
||||||
if (func->gc.flags & JANET_FUNCFLAG_TRACE) vm_do_trace(func);
|
if (func->gc.flags & JANET_FUNCFLAG_TRACE) {
|
||||||
|
vm_do_trace(func, fiber->stacktop - fiber->stackstart, stack);
|
||||||
|
}
|
||||||
if (janet_fiber_funcframe_tail(fiber, func)) {
|
if (janet_fiber_funcframe_tail(fiber, func)) {
|
||||||
janet_stack_frame(fiber->data + fiber->frame)->pc = pc;
|
janet_stack_frame(fiber->data + fiber->frame)->pc = pc;
|
||||||
int32_t n = fiber->stacktop - fiber->stackstart;
|
int32_t n = fiber->stacktop - fiber->stackstart;
|
||||||
@ -1186,6 +1176,11 @@ Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) {
|
|||||||
if (janet_vm_stackn >= JANET_RECURSION_GUARD)
|
if (janet_vm_stackn >= JANET_RECURSION_GUARD)
|
||||||
janet_panic("C stack recursed too deeply");
|
janet_panic("C stack recursed too deeply");
|
||||||
|
|
||||||
|
/* Tracing */
|
||||||
|
if (fun->gc.flags & JANET_FUNCFLAG_TRACE) {
|
||||||
|
vm_do_trace(fun, argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
/* Push frame */
|
/* Push frame */
|
||||||
janet_fiber_pushn(janet_vm_fiber, argv, argc);
|
janet_fiber_pushn(janet_vm_fiber, argv, argc);
|
||||||
if (janet_fiber_funcframe(janet_vm_fiber, fun)) {
|
if (janet_fiber_funcframe(janet_vm_fiber, fun)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user