Add os.environ (missing set: TODO)

This commit is contained in:
K. Lange 2021-01-08 16:36:24 +09:00
parent 0a9276863c
commit 3f66b85757

View File

@ -12,6 +12,9 @@
#include "../value.h"
#include "../object.h"
/* Did you know this is actually specified to not exist in a header? */
extern char ** environ;
#define S(c) (krk_copyString(c,sizeof(c)-1))
/**
@ -36,6 +39,64 @@ static KrkValue krk_uname(int argc, KrkValue argv[]) {
return result;
}
KrkValue krk_os_setenviron(int argc, KrkValue * argv[]) {
krk_runtimeError(vm.exceptions.typeError, "(unimplemented)");
return NONE_VAL();
}
static void _loadEnviron(KrkInstance * module) {
/* Create a new class to subclass `dict` */
KrkString * className = S("_Environ");
krk_push(OBJECT_VAL(className));
KrkClass * environClass = krk_newClass(className);
krk_attachNamedObject(&module->fields, "_Environ", (KrkObj*)environClass);
krk_pop(); /* className */
/* Inherit from base dict */
KrkValue dictClass;
krk_tableGet(&vm.builtins->fields,OBJECT_VAL(S("dict")), &dictClass);
krk_tableAddAll(&AS_CLASS(dictClass)->methods, &environClass->methods);
environClass->base = AS_CLASS(dictClass);
/* Add our set method that should also call dict's set method */
krk_defineNative(&environClass->methods, ".__set__", krk_os_setenviron);
krk_finalizeClass(environClass);
/* Start with an empty dictionary */
KrkInstance * environObj = AS_INSTANCE(krk_dict_of(0,NULL));
/* Transform it into an _Environ */
environObj->_class = environClass;
/* And attach it to the module */
krk_attachNamedObject(&module->fields, "environ", (KrkObj*)environObj);
/* Now load the environment into it */
if (!environ) return; /* Empty environment */
KrkClass * dictContents = environObj->_internal;
char ** env = environ;
for (; *env; env++) {
const char * equals = strchr(*env, '=');
if (!equals) continue;
size_t len = strlen(*env);
size_t keyLen = equals - *env;
size_t valLen = len - keyLen - 1;
KrkValue key = OBJECT_VAL(krk_copyString(*env, keyLen));
krk_push(key);
KrkValue val = OBJECT_VAL(krk_copyString(equals+1, valLen));
krk_push(val);
krk_tableSet(&dictContents->methods, key, val);
krk_pop(); /* val */
krk_pop(); /* key */
}
}
KrkValue krk_module_onload_os(void) {
KrkInstance * module = krk_newInstance(vm.moduleClass);
/* Store it on the stack for now so we can do stuff that may trip GC
@ -44,6 +105,8 @@ KrkValue krk_module_onload_os(void) {
krk_defineNative(&module->fields, "uname", krk_uname);
_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);