#include "env.h" #include "bitset.h" #include "util.h" #include "value.h" #include #include #include #include struct env { value_t **vals; // array of captured values size_t offset; // first index in De Bruijn space size_t length; // number of slots (offset .. last set bit) }; void env_free(env_t *caps) { if (caps) free(caps->vals); free(caps); } void env_mark_values(env_t *caps) { if (caps == NULL) return; for (size_t i = 0; i < caps->length; i++) { if (caps->vals[i] != NULL) value_mark_gc(caps->vals[i]); } } value_t *env_lookup(env_t *env, de_bruijn_t index) { if (env != NULL && index < env->length) return env->vals[index]; else return NULL; } /* ---------------- Capturing variables ---------------- */ env_t *env_capture(env_t *env, value_t **locals, size_t as_frame, size_t as_top, bitset_t *used) { //printf("BITS:"); //bitset_dump(used); size_t start = 0; size_t first = bitset_next(used, &start); if (first == (size_t)-1) return NULL; // empty capture size_t last = bitset_max(used); size_t length = last - first + 1; //printf("first: %zu, last: %zu, length: %zu\n", first,last,length); env_t *caps = malloc(sizeof(env_t)); if (caps == NULL) die("Out of memory: can't allocate captures"); caps->offset = first; caps->length = length; caps->vals = calloc(length, sizeof(value_t*)); // NULL slots by default if (caps->vals == NULL) die("Out of memory: can't allocate captures array"); start = first; size_t bit; while ((bit = bitset_next(used, &start)) != (size_t)-1 && bit <= last) { value_t *val = (bit >= as_frame) ? env_lookup(env, bit - as_frame) : locals[as_top - 1 - bit]; caps->vals[bit - first] = val; } return caps; } void env_debug_dump(env_t *env) { if (!env) return; for (int i = 0; i < env->length; i++) { if (env->vals[i]) { value_debug_dump(env->vals[i]); printf("%zu:", i + env->offset); } } }