Embed os, dir, time, fileio modules in core; only 'math' is still a separate shared library

This commit is contained in:
K. Lange 2021-02-15 16:27:50 +09:00
parent 1d8f308b0d
commit 34e7eb4e57
11 changed files with 115 additions and 143 deletions

View File

@ -1,7 +1,9 @@
#include <stdio.h>
#include <string.h>
#include "debug.h"
#include "vm.h"
#include "util.h"
void krk_disassembleChunk(FILE * f, KrkFunction * func, const char * name) {
KrkChunk * chunk = &func->chunk;
@ -180,3 +182,46 @@ size_t krk_disassembleInstruction(FILE * f, KrkFunction * func, size_t offset) {
return offset + size;
}
/**
* dis.dis(object)
*/
KRK_FUNC(dis,{
if (argc < 1) {
krk_runtimeError(vm.exceptions->argumentError, "dis() takes ");
return BOOLEAN_VAL(0);
}
if (IS_CLOSURE(argv[0])) {
KrkFunction * func = AS_CLOSURE(argv[0])->function;
krk_disassembleChunk(stdout, func, func->name ? func->name->chars : "(unnamed)");
} else if (IS_BOUND_METHOD(argv[0])) {
if (AS_BOUND_METHOD(argv[0])->method->type == OBJ_CLOSURE) {
KrkFunction * func = ((KrkClosure*)AS_BOUND_METHOD(argv[0])->method)->function;
const char * methodName = func->name ? func->name->chars : "(unnamed)";
const char * typeName = IS_CLASS(AS_BOUND_METHOD(argv[0])->receiver) ? AS_CLASS(AS_BOUND_METHOD(argv[0])->receiver)->name->chars : krk_typeName(AS_BOUND_METHOD(argv[0])->receiver);
char * tmp = malloc(strlen(methodName) + strlen(typeName) + 2);
sprintf(tmp, "%s.%s", typeName, methodName);
krk_disassembleChunk(stdout, func, tmp);
free(tmp);
} else {
krk_runtimeError(vm.exceptions->typeError, "Can not disassemble built-in method of '%s'", krk_typeName(AS_BOUND_METHOD(argv[0])->receiver));
}
} else if (IS_CLASS(argv[0])) {
krk_runtimeError(vm.exceptions->typeError, "todo: class disassembly");
} else {
krk_runtimeError(vm.exceptions->typeError, "Don't know how to disassemble '%s'", krk_typeName(argv[0]));
}
return NONE_VAL();
})
_noexport
void _createAndBind_disMod(void) {
KrkInstance * module = krk_newInstance(vm.baseClasses->moduleClass);
krk_attachNamedObject(&vm.modules, "dis", (KrkObj*)module);
krk_attachNamedObject(&module->fields, "__name__", (KrkObj*)S("dis"));
krk_attachNamedValue(&module->fields, "__file__", NONE_VAL());
krk_attachNamedObject(&module->fields, "__doc__",
(KrkObj*)S("Provides tools for disassembling bytecode."));
BIND_FUNC(module, dis);
}

View File

@ -7,3 +7,4 @@
extern void krk_disassembleChunk(FILE * f, KrkFunction * func, const char * name);
extern size_t krk_disassembleInstruction(FILE * f, KrkFunction * func, size_t offset);
extern size_t krk_lineNumber(KrkChunk * chunk, size_t offset);
extern void _createAndBind_disMod(void);

View File

@ -1,5 +1,5 @@
/**
* Native module for providing access to stdio.
* Provides an interface to C FILE* streams.
*/
#include <assert.h>
#include <stdio.h>
@ -462,11 +462,14 @@ KRK_METHOD(Directory,__repr__,{
return OBJECT_VAL(out);
})
KrkValue krk_module_onload_fileio(void) {
_noexport
void _createAndBind_fileioMod(void) {
KrkInstance * module = krk_newInstance(vm.baseClasses->moduleClass);
/* Store it on the stack for now so we can do stuff that may trip GC
* and not lose it to garbage colletion... */
krk_push(OBJECT_VAL(module));
krk_attachNamedObject(&vm.modules, "fileio", (KrkObj*)module);
krk_attachNamedObject(&module->fields, "__name__", (KrkObj*)S("fileio"));
krk_attachNamedValue(&module->fields, "__file__", NONE_VAL());
krk_attachNamedObject(&module->fields, "__doc__",
(KrkObj*)S("Provides access to C <stdio> buffered file I/O functions."));
/* Define a class to represent files. (Should this be a helper method?) */
krk_makeClass(module, &File, "File", vm.baseClasses->objectClass);
@ -511,9 +514,4 @@ KrkValue krk_module_onload_fileio(void) {
/* Our base will be the open method */
BIND_FUNC(module,open);
BIND_FUNC(module,opendir);
/* Pop the module object before returning; it'll get pushed again
* by the VM before the GC has a chance to run, so it's safe. */
assert(AS_INSTANCE(krk_pop()) == module);
return OBJECT_VAL(module);
}

View File

@ -465,10 +465,6 @@ _finishArgs:
#ifdef BUNDLE_LIBS
/* Add any other modules you want to include that are normally built as shared objects. */
BUNDLED(fileio);
BUNDLED(dis);
BUNDLED(os);
BUNDLED(time);
BUNDLED(math);
#endif

View File

@ -1,61 +0,0 @@
/**
* Currently just dis().
*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "vm.h"
#include "value.h"
#include "object.h"
#include "debug.h"
#define S(c) (krk_copyString(c,sizeof(c)-1))
/**
* dis.dis(object)
*/
static KrkValue krk_dis(int argc, KrkValue argv[], int hasKw) {
if (argc < 1) {
krk_runtimeError(vm.exceptions->argumentError, "dis() takes ");
return BOOLEAN_VAL(0);
}
#ifdef ENABLE_DISASSEMBLY
if (IS_CLOSURE(argv[0])) {
KrkFunction * func = AS_CLOSURE(argv[0])->function;
krk_disassembleChunk(stdout, func, func->name ? func->name->chars : "(unnamed)");
} else if (IS_BOUND_METHOD(argv[0])) {
if (AS_BOUND_METHOD(argv[0])->method->type == OBJ_CLOSURE) {
KrkFunction * func = ((KrkClosure*)AS_BOUND_METHOD(argv[0])->method)->function;
const char * methodName = func->name ? func->name->chars : "(unnamed)";
const char * typeName = IS_CLASS(AS_BOUND_METHOD(argv[0])->receiver) ? AS_CLASS(AS_BOUND_METHOD(argv[0])->receiver)->name->chars : krk_typeName(AS_BOUND_METHOD(argv[0])->receiver);
char * tmp = malloc(strlen(methodName) + strlen(typeName) + 2);
sprintf(tmp, "%s.%s", typeName, methodName);
krk_disassembleChunk(stdout, func, tmp);
free(tmp);
} else {
krk_runtimeError(vm.exceptions->typeError, "Can not disassemble built-in method of '%s'", krk_typeName(AS_BOUND_METHOD(argv[0])->receiver));
}
} else if (IS_CLASS(argv[0])) {
krk_runtimeError(vm.exceptions->typeError, "todo: class disassembly");
} else {
krk_runtimeError(vm.exceptions->typeError, "Don't know how to disassemble '%s'", krk_typeName(argv[0]));
}
#else
krk_runtimeError(vm.exceptions->typeError, "Kuroko was built with debug methods stripped; disassembly is not available.");
#endif
return NONE_VAL();
}
KrkValue krk_module_onload_dis(void) {
KrkInstance * module = krk_newInstance(vm.baseClasses->moduleClass);
krk_push(OBJECT_VAL(module));
krk_defineNative(&module->fields, "dis", krk_dis);
assert(AS_INSTANCE(krk_pop()) == module);
return OBJECT_VAL(module);
}

View File

@ -1,55 +0,0 @@
/**
* Currently just sleep().
*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include "vm.h"
#include "value.h"
#include "object.h"
#define S(c) (krk_copyString(c,sizeof(c)-1))
/**
* system.sleep(seconds)
*/
static KrkValue _time_sleep(int argc, KrkValue argv[], int hasKw) {
if (argc < 1) {
krk_runtimeError(vm.exceptions->argumentError, "sleep: expect at least one argument.");
return BOOLEAN_VAL(0);
}
/* Accept an integer or a floating point. Anything else, just ignore. */
unsigned int usecs = (IS_INTEGER(argv[0]) ? AS_INTEGER(argv[0]) :
(IS_FLOATING(argv[0]) ? AS_FLOATING(argv[0]) : 0)) *
1000000;
usleep(usecs);
return BOOLEAN_VAL(1);
}
static KrkValue _time_time(int argc, KrkValue argv[], int hasKw) {
time_t out = time(NULL);
return FLOATING_VAL(out); /* TODO actually support subsecond values */
}
KrkValue krk_module_onload_time(void) {
KrkInstance * module = krk_newInstance(vm.baseClasses->moduleClass);
/* Store it on the stack for now so we can do stuff that may trip GC
* and not lose it to garbage colletion... */
krk_push(OBJECT_VAL(module));
krk_defineNative(&module->fields, "sleep", _time_sleep);
krk_defineNative(&module->fields, "time", _time_time);
/* Pop the module object before returning; it'll get pushed again
* by the VM before the GC has a chance to run, so it's safe. */
assert(AS_INSTANCE(krk_pop()) == module);
return OBJECT_VAL(module);
}

View File

@ -1,6 +1,3 @@
/**
* Currently just uname().
*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
@ -480,11 +477,14 @@ KRK_FUNC(execvp,{
return krk_runtimeError(OSError, "Expected to not return from exec, but did.");
})
KrkValue krk_module_onload_os(void) {
_noexport
void _createAndBind_osMod(void) {
KrkInstance * module = krk_newInstance(vm.baseClasses->moduleClass);
/* Store it on the stack for now so we can do stuff that may trip GC
* and not lose it to garbage colletion... */
krk_push(OBJECT_VAL(module));
krk_attachNamedObject(&vm.modules, "os", (KrkObj*)module);
krk_attachNamedObject(&module->fields, "__name__", (KrkObj*)S("os"));
krk_attachNamedValue(&module->fields, "__file__", NONE_VAL());
krk_attachNamedObject(&module->fields, "__doc__",
(KrkObj*)S("Provides access to low-level system operations."));
#ifdef _WIN32
krk_attachNamedObject(&module->fields, "name", (KrkObj*)S("nt"));
@ -590,11 +590,6 @@ KrkValue krk_module_onload_os(void) {
_loadEnviron(module);
/* Pop the module object before returning; it'll get pushed again
* by the VM before the GC has a chance to run, so it's safe. */
assert(AS_INSTANCE(krk_pop()) == module);
return OBJECT_VAL(module);
}

46
src/time.c Normal file
View File

@ -0,0 +1,46 @@
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include "vm.h"
#include "value.h"
#include "object.h"
#include "util.h"
KRK_FUNC(sleep,{
FUNCTION_TAKES_EXACTLY(1);
if (!IS_INTEGER(argv[0]) && !IS_FLOATING(argv[0])) {
return TYPE_ERROR(int or float,argv[0]);
}
unsigned int usecs = (IS_INTEGER(argv[0]) ? AS_INTEGER(argv[0]) :
(IS_FLOATING(argv[0]) ? AS_FLOATING(argv[0]) : 0)) *
1000000;
usleep(usecs);
return BOOLEAN_VAL(1);
})
KRK_FUNC(time,{
FUNCTION_TAKES_NONE();
time_t out = time(NULL);
return FLOATING_VAL(out);
})
_noexport
void _createAndBind_timeMod(void) {
KrkInstance * module = krk_newInstance(vm.baseClasses->moduleClass);
krk_attachNamedObject(&vm.modules, "time", (KrkObj*)module);
krk_attachNamedObject(&module->fields, "__name__", (KrkObj*)S("time"));
krk_attachNamedValue(&module->fields, "__file__", NONE_VAL());
krk_attachNamedObject(&module->fields, "__doc__",
(KrkObj*)S("Provides timekeeping functions."));
BIND_FUNC(module,sleep);
BIND_FUNC(module,time);
}

View File

@ -1162,6 +1162,10 @@ void krk_initVM(int flags) {
_createAndBind_setClass();
_createAndBind_exceptions();
_createAndBind_gcMod();
_createAndBind_disMod();
_createAndBind_timeMod();
_createAndBind_osMod();
_createAndBind_fileioMod();
#ifdef ENABLE_THREADING
_createAndBind_threadsMod();
#endif

View File

@ -233,6 +233,9 @@ extern void _createAndBind_builtins(void);
extern void _createAndBind_type(void);
extern void _createAndBind_exceptions(void);
extern void _createAndBind_gcMod(void);
extern void _createAndBind_timeMod(void);
extern void _createAndBind_osMod(void);
extern void _createAndBind_fileioMod(void);
extern int krk_doRecursiveModuleLoad(KrkString * name);

View File

@ -1,2 +1,2 @@
oh no! sleep: expect at least one argument.
oh no! sleep() takes exactly 1 argument (0 given)
Back from try/except