From fe2bcf8ae632af3c8a1e491b298a98b83010fd40 Mon Sep 17 00:00:00 2001 From: CPunch Date: Fri, 27 Nov 2020 19:34:54 -0600 Subject: [PATCH] fixed GC bug, extended strings --- src/clex.c | 27 +++++++++++++++++++++++---- src/clex.h | 2 +- src/ctable.c | 9 ++++----- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/clex.c b/src/clex.c index 0322c64..447ee6c 100644 --- a/src/clex.c +++ b/src/clex.c @@ -63,7 +63,7 @@ static void saveBuffer(CLexState *state) { } // resets the lex state buffer & returns the allocated buffer as a null terminated string -static char *cutBuffer(CLexState *state) { +static char *cutBuffer(CLexState *state, int *length) { // append the null terminator appendBuffer(state, '\0'); @@ -72,6 +72,8 @@ static char *cutBuffer(CLexState *state) { size_t count = state->bufCount; size_t cap = state->bufCap; + *length = count - 1; + // reset lex state buffer! resetBuffer(state); @@ -85,8 +87,7 @@ static CToken makeToken(CLexState *state, CTokenType type) { token.line = state->line; if (isBuffer(state)) { // is the buffer heap-allocated? - token.length = state->bufCount; - token.start = cutBuffer(state); + token.start = cutBuffer(state, &token.length); } else { token.start = state->startChar; token.length = state->currentChar - state->startChar; // delta between start & current @@ -201,8 +202,26 @@ CToken parseString(CLexState *state) { case 'r': case 'n': appendBuffer(state, '\n'); break; case 't': appendBuffer(state, '\t'); break; case '\\': appendBuffer(state, '\\'); break; - default: + default: { + if (isNumerical(peek(state))) { + char *numStart = state->currentChar; + + // consume the number + while (isNumerical(peek(state))) + next(state); + state->currentChar--; // since next() is called after + + int num = (int)strtol(numStart, NULL, 10); + + if (num > 255) // sanity check + return makeError(state, "Character out of range! > 255!"); + + appendBuffer(state, num); + break; + } + return makeError(state, "Unknown special character!"); // TODO: maybe a more descriptive error? + } } next(state); // consume special character diff --git a/src/clex.h b/src/clex.h index effa189..cd4f003 100644 --- a/src/clex.h +++ b/src/clex.h @@ -34,7 +34,7 @@ typedef enum { // literals TOKEN_IDENTIFIER, - TOKEN_STRING, + TOKEN_STRING, // token.start is heap allocated and separate from the source string! TOKEN_NUMBER, TOKEN_NIL, TOKEN_TRUE, diff --git a/src/ctable.c b/src/ctable.c index 0c8f24e..ede7763 100644 --- a/src/ctable.c +++ b/src/ctable.c @@ -107,8 +107,8 @@ static CTableEntry *findEntry(CTableEntry *entries, int mask, CValue key) { } } -static void resizeTbl(CState *state, CTable *tbl, size_t newCapacity) { - if (cosmoT_checkShrink(state, tbl)) +static void resizeTbl(CState *state, CTable *tbl, int newCapacity, bool canShrink) { + if (canShrink && cosmoT_checkShrink(state, tbl)) return; size_t size = sizeof(CTableEntry) * newCapacity; @@ -152,8 +152,7 @@ static void resizeTbl(CState *state, CTable *tbl, size_t newCapacity) { bool cosmoT_checkShrink(CState *state, CTable *tbl) { // if count > 8 and active entries < tombstones if (tbl->count > MIN_TABLE_CAPACITY && (tbl->count - tbl->tombstones < tbl->tombstones || tbl->tombstones > 50)) { - tbl->tombstones = 0; - resizeTbl(state, tbl, nextPow2((tbl->count - tbl->tombstones) * GROW_FACTOR)); // shrink based on active entries to the next pow of 2 + resizeTbl(state, tbl, nextPow2(tbl->count - tbl->tombstones) * GROW_FACTOR, false); // shrink based on active entries to the next pow of 2 return true; } @@ -166,7 +165,7 @@ COSMO_API CValue* cosmoT_insert(CState *state, CTable *tbl, CValue key) { if (tbl->count + 1 > (int)(tbl->capacity * MAX_TABLE_FILL)) { // grow table int newCap = tbl->capacity * GROW_FACTOR; - resizeTbl(state, tbl, newCap); + resizeTbl(state, tbl, newCap, true); } // insert into the table