#include "priv.h" #include #include struct Stack { VALUE* stack; size_t stack_n; size_t stack_cap; uint32_t* fp; size_t fp_n; size_t fp_cap; }; Stack* stack_new(void) { Stack* s = xcalloc(1, sizeof(Stack)); s->stack_n = 0; s->fp_n = 0; s->stack_cap = 64; s->fp_cap = 8; s->stack = xmalloc(s->stack_cap * sizeof s->stack[0]); s->fp = xmalloc(s->stack_cap * sizeof s->fp[0]); assert(s->stack); assert(s->fp); stack_push_fp(s); return s; } void stack_destroy(Stack* s) { free(s->stack); free(s->fp); free(s); } TYC_RESULT stack_push(Stack* s, VALUE v) { if (s->stack_n == s->stack_cap) { s->stack_cap *= 2; s->stack = xrealloc(s->stack, s->stack_cap * sizeof s->stack[0]); assert(s->stack); } s->stack[s->stack_n] = v; ++s->stack_n; return T_OK; } size_t stack_top_fp(Stack* s) { return s->fp[s->fp_n - 1]; } TYC_RESULT stack_peek(Stack* s, VALUE* v_out) { if (s->stack_n <= stack_top_fp(s)) return T_ERR_STACK_UNDERFLOW; if (v_out) *v_out = s->stack[s->stack_n - 1]; return T_OK; } TYC_RESULT stack_pop(Stack* s, VALUE* v_out) { TYC_RESULT err = stack_peek(s, v_out); if (err) return err; --s->stack_n; return T_OK; } size_t stack_len(Stack* s) { return s->stack_n - stack_top_fp(s); } TYC_RESULT stack_at(Stack* s, int32_t key, VALUE* v) { if (key >= 0) { if ((int) stack_top_fp(s) + key >= (int) s->stack_n) return T_ERR_STACK_ACCESS_OUT_OF_RANGE; *v = s->stack[(int) stack_top_fp(s) + key]; } else { if ((int) s->stack_n + key < (int) stack_top_fp(s)) return T_ERR_STACK_ACCESS_OUT_OF_RANGE; *v = s->stack[(int) s->stack_n + key]; } return T_OK; } TYC_RESULT stack_set(Stack* s, int32_t key, VALUE v) { if (key >= 0) { if ((int) stack_top_fp(s) + key >= (int) s->stack_n) return T_ERR_STACK_ACCESS_OUT_OF_RANGE; s->stack[(int) stack_top_fp(s) + key] = v; } else { if ((int) s->stack_n + key < (int) stack_top_fp(s)) return T_ERR_STACK_ACCESS_OUT_OF_RANGE; s->stack[(int) s->stack_n + key] = v; } return T_OK; } TYC_RESULT stack_push_fp(Stack* s) { if (s->fp_n == s->fp_cap) { s->fp_cap *= 2; s->fp = xrealloc(s->fp, s->fp_cap * sizeof s->fp[0]); assert(s->fp); } s->fp[s->fp_n] = (uint32_t) s->stack_n; ++s->fp_n; return T_OK; } TYC_RESULT stack_pop_fp(Stack* s) { if (s->fp_n == 1) return T_ERR_STACK_FP_UNDERFLOW; s->stack_n = stack_top_fp(s); --s->fp_n; return T_OK; } size_t stack_fp_level(Stack* s) { return s->fp_n; } size_t stack_collectable_array(Stack* s, VALUE** values) { size_t j = 0; *values = xmalloc(stack_len(s) * sizeof(VALUE)); for (size_t i = 0; i < s->stack_n; ++i) if (type_is_collectable(s->stack[i].type)) (*values)[j++] = s->stack[i]; return j; }