From 09e56c2c359fc9723e42b986ad8f58af1fae7044 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sun, 14 Sep 2014 01:08:37 +0900 Subject: [PATCH] upgrade xvect.h --- codegen.c | 38 +++++----- include/picrin/xvect.h | 160 +++++++++++++++++++++++++++++++++++------ 2 files changed, 157 insertions(+), 41 deletions(-) diff --git a/codegen.c b/codegen.c index b593a5d1..d9238456 100644 --- a/codegen.c +++ b/codegen.c @@ -198,13 +198,13 @@ lookup_scope(analyze_scope *scope, pic_sym sym) size_t i; /* args */ - for (i = 0; i < scope->args.size; ++i) { + for (i = 0; i < xv_size(&scope->args); ++i) { arg = xv_get(&scope->args, i); if (*arg == sym) return true; } /* locals */ - for (i = 0; i < scope->locals.size; ++i) { + for (i = 0; i < xv_size(&scope->locals); ++i) { local = xv_get(&scope->locals, i); if (*local == sym) return true; @@ -218,13 +218,13 @@ capture_var(analyze_scope *scope, pic_sym sym) pic_sym *var; size_t i; - for (i = 0; i < scope->captures.size; ++i) { + for (i = 0; i < xv_size(&scope->captures); ++i) { var = xv_get(&scope->captures, i); if (*var == sym) { break; } } - if (i == scope->captures.size) { + if (i == xv_size(&scope->captures)) { xv_push(&scope->captures, &sym); } } @@ -384,7 +384,7 @@ analyze_procedure(analyze_state *state, pic_value name, pic_value formals, pic_v size_t i; args = pic_nil_value(); - for (i = scope->args.size; i > 0; --i) { + for (i = xv_size(&scope->args); i > 0; --i) { var = xv_get(&scope->args, i - 1); pic_push(pic, pic_sym_value(*var), args); } @@ -399,13 +399,13 @@ analyze_procedure(analyze_state *state, pic_value name, pic_value formals, pic_v analyze_deferred(state); locals = pic_nil_value(); - for (i = scope->locals.size; i > 0; --i) { + for (i = xv_size(&scope->locals); i > 0; --i) { var = xv_get(&scope->locals, i - 1); pic_push(pic, pic_sym_value(*var), locals); } captures = pic_nil_value(); - for (i = scope->captures.size; i > 0; --i) { + for (i = xv_size(&scope->captures); i > 0; --i) { var = xv_get(&scope->captures, i - 1); pic_push(pic, pic_sym_value(*var), captures); } @@ -940,21 +940,21 @@ create_activation(codegen_context *cxt) xh_init_int(®s, sizeof(size_t)); offset = 1; - for (i = 0; i < cxt->args.size; ++i) { + for (i = 0; i < xv_size(&cxt->args); ++i) { var = xv_get(&cxt->args, i); n = i + offset; xh_put_int(®s, *var, &n); } offset += i; - for (i = 0; i < cxt->locals.size; ++i) { + for (i = 0; i < xv_size(&cxt->locals); ++i) { var = xv_get(&cxt->locals, i); n = i + offset; xh_put_int(®s, *var, &n); } - for (i = 0; i < cxt->captures.size; ++i) { + for (i = 0; i < xv_size(&cxt->captures); ++i) { var = xv_get(&cxt->captures, i); - if ((n = xh_val(xh_get_int(®s, *var), size_t)) <= cxt->args.size || (cxt->varg && n == cxt->args.size + 1)) { + if ((n = xh_val(xh_get_int(®s, *var), size_t)) <= xv_size(&cxt->args) || (cxt->varg && n == xv_size(&cxt->args) + 1)) { /* copy arguments to capture variable area */ cxt->code[cxt->clen].insn = OP_LREF; cxt->code[cxt->clen].u.i = n; @@ -1031,9 +1031,9 @@ pop_codegen_context(codegen_state *state) irep = (struct pic_irep *)pic_obj_alloc(pic, sizeof(struct pic_irep), PIC_TT_IREP); irep->name = state->cxt->name; irep->varg = state->cxt->varg; - irep->argc = state->cxt->args.size + 1; - irep->localc = state->cxt->locals.size; - irep->capturec = state->cxt->captures.size; + irep->argc = xv_size(&state->cxt->args) + 1; + irep->localc = xv_size(&state->cxt->locals); + irep->capturec = xv_size(&state->cxt->captures); irep->code = pic_realloc(pic, state->cxt->code, sizeof(pic_code) * state->cxt->clen); irep->clen = state->cxt->clen; irep->irep = pic_realloc(pic, state->cxt->irep, sizeof(struct pic_irep *) * state->cxt->ilen); @@ -1065,7 +1065,7 @@ index_capture(codegen_state *state, pic_sym sym, int depth) cxt = cxt->up; } - for (i = 0; i < cxt->captures.size; ++i) { + for (i = 0; i < xv_size(&cxt->captures); ++i) { var = xv_get(&cxt->captures, i); if (*var == sym) return i; @@ -1081,13 +1081,13 @@ index_local(codegen_state *state, pic_sym sym) pic_sym *var; offset = 1; - for (i = 0; i < cxt->args.size; ++i) { + for (i = 0; i < xv_size(&cxt->args); ++i) { var = xv_get(&cxt->args, i); if (*var == sym) return i + offset; } offset += i; - for (i = 0; i < cxt->locals.size; ++i) { + for (i = 0; i < xv_size(&cxt->locals); ++i) { var = xv_get(&cxt->locals, i); if (*var == sym) return i + offset; @@ -1128,7 +1128,7 @@ codegen(codegen_state *state, pic_value obj) name = pic_sym(pic_list_ref(pic, obj, 1)); if ((i = index_capture(state, name, 0)) != -1) { cxt->code[cxt->clen].insn = OP_LREF; - cxt->code[cxt->clen].u.i = i + cxt->args.size + cxt->locals.size + 1; + cxt->code[cxt->clen].u.i = i + xv_size(&cxt->args) + xv_size(&cxt->locals) + 1; cxt->clen++; return; } @@ -1174,7 +1174,7 @@ codegen(codegen_state *state, pic_value obj) name = pic_sym(pic_list_ref(pic, var, 1)); if ((i = index_capture(state, name, 0)) != -1) { cxt->code[cxt->clen].insn = OP_LSET; - cxt->code[cxt->clen].u.i = i + cxt->args.size + cxt->locals.size + 1; + cxt->code[cxt->clen].u.i = i + xv_size(&cxt->args) + xv_size(&cxt->locals) + 1; cxt->clen++; cxt->code[cxt->clen].insn = OP_PUSHNONE; cxt->clen++; diff --git a/include/picrin/xvect.h b/include/picrin/xvect.h index ec68a2cb..b98886e9 100644 --- a/include/picrin/xvect.h +++ b/include/picrin/xvect.h @@ -2,40 +2,52 @@ #define XVECT_H__ /* - * Copyright (c) 2014 by Yuichi Nishiwaki + * Copyright (c) 2014 by Yuichi Nishiwaki */ #if defined(__cplusplus) extern "C" { #endif +#include #include #include +#include typedef struct xvect { char *data; - size_t size, capa, width; + size_t size, mask, head, tail, width; } xvect; static inline void xv_init(xvect *, size_t); static inline void xv_destroy(xvect *); +static inline size_t xv_size(xvect *); + static inline void xv_reserve(xvect *, size_t); +static inline void xv_shrink(xvect *, size_t); static inline void *xv_get(xvect *, size_t); static inline void xv_set(xvect *, size_t, void *); static inline void xv_push(xvect *, void *); -static inline void *xv_peek(xvect *); static inline void *xv_pop(xvect *); +static inline void *xv_shift(xvect *); +static inline void xv_unshift(xvect *, void *); + +static inline void xv_splice(xvect *, size_t, size_t); +static inline void xv_insert(xvect *, size_t, void *); + static inline void xv_init(xvect *x, size_t width) { x->data = NULL; - x->size = 0; - x->capa = 0; x->width = width; + x->size = 0; + x->mask = -1; + x->head = 0; + x->tail = 0; } static inline void @@ -44,44 +56,148 @@ xv_destroy(xvect *x) free(x->data); } -static inline void -xv_reserve(xvect *x, size_t newcapa) +static inline size_t +xv_size(xvect *x) { - x->data = realloc(x->data, newcapa * x->width); - x->capa = newcapa; + return x->tail < x->head + ? x->tail + x->size - x->head + : x->tail - x->head; +} + +static inline size_t +xv_round2(size_t x) +{ + x -= 1; + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + x |= (x >> 32); + x++; + return x; +} + +static inline void +xv_rotate(xvect *x) +{ + if (x->tail < x->head) { + char buf[x->size * x->width]; + + /* perform rotation */ + memcpy(buf, x->data, sizeof buf); + memcpy(x->data, buf + x->head * x->width, (x->size - x->head) * x->width); + memcpy(x->data + (x->size - x->head) * x->width, buf, x->tail * x->width); + x->tail = x->size - x->head + x->tail; + x->head = 0; + } +} + +static inline void +xv_adjust(xvect *x, size_t size) +{ + size = xv_round2(size); + if (size != x->size) { + xv_rotate(x); + x->data = realloc(x->data, size * x->width); + x->size = size; + x->mask = size - 1; + } +} + +static inline void +xv_reserve(xvect *x, size_t mincapa) +{ + if (x->size < mincapa + 1) { + xv_adjust(x, mincapa + 1); /* capa == size - 1 */ + } +} + +static inline void +xv_shrink(xvect *x, size_t maxcapa) +{ + if (x->size > maxcapa + 1) { + xv_adjust(x, maxcapa + 1); /* capa == size - 1 */ + } } static inline void * xv_get(xvect *x, size_t i) { - return x->data + i * x->width; + assert(i < xv_size(x)); + + return x->data + ((x->head + i) & x->mask) * x->width; } static inline void xv_set(xvect *x, size_t i, void *src) { - memcpy(x->data + i * x->width, src, x->width); + memcpy(xv_get(x, i), src, x->width); } static inline void xv_push(xvect *x, void *src) { - if (x->capa <= x->size + 1) { - xv_reserve(x, x->size * 2 + 1); - } - xv_set(x, x->size++, src); -} - -static inline void * -xv_peek(xvect *x) -{ - return xv_get(x, x->size); + xv_reserve(x, xv_size(x) + 1); + x->tail = (x->tail + 1) & x->mask; + xv_set(x, xv_size(x) - 1, src); } static inline void * xv_pop(xvect *x) { - return xv_get(x, --x->size); + void *dat; + + assert(xv_size(x) >= 1); + + dat = xv_get(x, xv_size(x) - 1); + x->tail = (x->tail - 1) & x->mask; + return dat; +} + +static inline void * +xv_shift(xvect *x) +{ + void *dat; + + assert(xv_size(x) >= 1); + + dat = xv_get(x, 0); + x->head = (x->head + 1) & x->mask; + return dat; +} + +static inline void +xv_unshift(xvect *x, void *src) +{ + xv_reserve(x, xv_size(x) + 1); + x->head = (x->head - 1) & x->mask; + xv_set(x, 0, src); +} + +static inline void +xv_splice(xvect *x, size_t i, size_t j) +{ + assert(i <= j && j < xv_size(x)); + + xv_rotate(x); + memmove(xv_get(x, i), xv_get(x, j), (xv_size(x) - j) * x->width); + x->tail = (x->tail - j + i) & x->mask; +} + +static inline void +xv_insert(xvect *x, size_t i, void *src) +{ + assert(i <= xv_size(x)); + + xv_reserve(x, xv_size(x) + 1); + xv_rotate(x); + x->tail = (x->tail + 1) & x->mask; + + if (xv_size(x) - 1 != i) { + memmove(xv_get(x, i + 1), xv_get(x, i), (xv_size(x) - 1 - i) * x->width); + } + xv_set(x, i, src); } #if defined(__cplusplus)