From 139e9125484822f232fc6987a979ef6ec119603a Mon Sep 17 00:00:00 2001 From: Sage Vaillancourt Date: Wed, 27 Apr 2022 16:44:00 -0400 Subject: [PATCH] Add a simple assert() macro. assert() is disabled when calling make release Support negative numbers! --- src/Makefile | 2 +- src/hash.c | 20 ++++++++++------- src/main.c | 18 ++++++++------- src/object.c | 11 ++++++---- src/object.h | 6 +++++ src/pebblisp.c | 52 ++++++++++++++++++++++---------------------- src/plfunc/general.c | 12 +++------- 7 files changed, 65 insertions(+), 56 deletions(-) diff --git a/src/Makefile b/src/Makefile index 06f728e..e4834c6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -26,7 +26,7 @@ val: notest ./tests.sh -val release_notest: - gcc -O3 $(GCC_ARGS) $(file_libs) && strip ./$(exe) + gcc -O3 $(GCC_ARGS) -D RELEASE $(file_libs) && strip ./$(exe) release: release_notest echo && ./tests.sh diff --git a/src/hash.c b/src/hash.c index e69e82a..1dd5ba8 100644 --- a/src/hash.c +++ b/src/hash.c @@ -8,14 +8,16 @@ size_t addStripped(struct ObjectTable* table, char* name, struct StrippedObject object); +char* ERROR_ARRAY[1] = {"ERROR THIS VALUE SHOULD BE IGNORED"}; + Object deStrip(struct StrippedObject object) { - // Garbage .forward data may be safe here, but since usage of that data is - // currently in flux, it should take the more cautious route for now. + // Garbage .forward/.docStrings data may be safe here. + // Usage of that data is currently in flux, so it has a very noisy value for now. return (Object) { .type = object.type, .string = object.data, - .forward = NULL, + .docStrings = ERROR_ARRAY, }; } @@ -130,6 +132,7 @@ static size_t hash(unused const char* str, struct ObjectTable* table) */ size_t addStripped(struct ObjectTable* table, char* name, struct StrippedObject object) { + assert(table); extendTable(table); size_t initial = hash(name, table); size_t h = initial % table->capacity; @@ -171,12 +174,13 @@ Object buildHashTable(Object* params, int length, struct Environment* env) capacity = params[0].number; } - Object table = newObject(TYPE_HASH_TABLE); - table.table = malloc(sizeof(struct ObjectTableObject)); - table.table->table = buildTable(capacity); - table.table->refs = 1; + struct ObjectTableObject* table = malloc(sizeof(struct ObjectTableObject)); + table->table = buildTable(capacity); + table->refs = 1; - return table; + Object tableObject = newObject(TYPE_HASH_TABLE); + tableObject.data = table; + return tableObject; } Object addToHashTable(Object* params, int length, struct Environment* env) diff --git a/src/main.c b/src/main.c index 371e741..5b59416 100644 --- a/src/main.c +++ b/src/main.c @@ -102,15 +102,17 @@ void repl(struct Environment* env) } add_history(buf); - if (buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' ') { + int isCd = strncmp("cd ", buf, 3); + int isHelp = buf[0] == '?' && (buf[1] == ' ' || buf[1] == '\0'); + if (isCd || isHelp) { char* oldBuf = buf; - buf = malloc(sizeof(char) * strlen(buf + 3) + 8); - sprintf(buf, "(cd \"%s\")", oldBuf + 3); - free(oldBuf); - } else if (buf[0] == '?' && (buf[1] == ' ' || buf[1] == '\0')) { - char* oldBuf = buf; - buf = malloc(sizeof(char) * (strlen(buf) + 3)); - sprintf(buf, "(%s)", oldBuf); + if (isCd) { + buf = malloc(sizeof(char) * strlen(buf + 3) + 8); + sprintf(buf, "(cd \"%s\")", oldBuf + 3); + } else { + buf = malloc(sizeof(char) * (strlen(buf) + 3)); + sprintf(buf, "(%s)", oldBuf); + } free(oldBuf); } diff --git a/src/object.c b/src/object.c index d6140a2..62f3063 100644 --- a/src/object.c +++ b/src/object.c @@ -42,6 +42,7 @@ void* scalloc(size_t size, size_t count) */ int listLength(const Object* listObj) { + assert(isListy(*listObj)); int len = 0; FOR_POINTER_IN_LIST(listObj) { len++; @@ -56,10 +57,7 @@ int listLength(const Object* listObj) */ Object* tail(const Object* listObj) { - if (!isListy(*listObj)) { - return NULL; - } - + assert(isListy(*listObj)); Object* tail = NULL; FOR_POINTER_IN_LIST(listObj) { tail = POINTER; @@ -491,6 +489,8 @@ void printAndClean(Object* target) */ void deleteList(Object* dest) { + assert(isListy(*dest)); + Object* march = dest->list; while (march != NULL) { Object* prevMarch = march; @@ -511,6 +511,8 @@ void deleteList(Object* dest) */ Object cloneList(const Object* src) { + assert(isListy(*src)); + Object BuildListNamed(list); FOR_POINTER_IN_LIST(src) { addToList(list, cloneObject(*POINTER)); @@ -647,6 +649,7 @@ inline Object cloneObject(const Object src) Object cloneStruct(const Object src) { + assert(src.type == TYPE_STRUCT); Object structo = structObject(src.structObject->definition); struct StructObject* so = structo.structObject; for (int i = 0; i < getStructAt(so->definition)->fieldCount; i++) { diff --git a/src/object.h b/src/object.h index c5943f1..2c344ba 100644 --- a/src/object.h +++ b/src/object.h @@ -19,6 +19,12 @@ #define printd(...) do { } while (0) #endif +#ifdef RELEASE +#define assert(...) do { } while (0) +#else +#define assert(...) do {if (!(__VA_ARGS__)) {eprintf("\nassertion '" # __VA_ARGS__ "' at %s:%d failed!\nBailing!\n", __FILE__, __LINE__); int* X = NULL; unused int Y = *X;}} while (0) +#endif + #define MAX_TOK_CNT 2048 #define FOR_POINTER_IN_LIST(_list) \ diff --git a/src/pebblisp.c b/src/pebblisp.c index c079980..017afaf 100644 --- a/src/pebblisp.c +++ b/src/pebblisp.c @@ -203,9 +203,8 @@ Object listEvalLambda(Object* lambda, const Object* passedArguments, int evalLen deleteEnv(&newEnv); cleanObject(lambda); - Object* t = tail(&ret); - if (t) { - Object o = cloneObject(*t); + if (isListy(ret)) { + Object o = cloneObject(*tail(&ret)); cleanObject(&ret); return o; } @@ -223,19 +222,14 @@ Object listEvalLambda(Object* lambda, const Object* passedArguments, int evalLen Object funcyEval(Object* funcy, const Object* passedArguments, int evalLength, struct Environment* env) { - if (!funcy) { - eprintf("HIGHLY ILLEGAL NULL FUNC-LIKE!!!\n"); - throw(BAD_TYPE, "Expected func-like object, but received null"); - } - switch (funcy->type) { - case TYPE_LAMBDA: - return listEvalLambda(funcy, passedArguments, evalLength, env); - case TYPE_FUNC: - return listEvalFunc(funcy, passedArguments, evalLength, env); - default: - eprintf("HIGHLY ILLEGAL NOT-FUNC IN funcyEval()!!!\n"); - throw(BAD_TYPE, "Expected func-like object, but received %s", getTypeName(funcy)); + assert(funcy != NULL); + assert(isFuncy(*funcy)); + + if (funcy->type == TYPE_LAMBDA) { + return listEvalLambda(funcy, passedArguments, evalLength, env); } + + return listEvalFunc(funcy, passedArguments, evalLength, env); } /** @@ -390,11 +384,10 @@ Object structAccess(Object* params, unused int length, unused struct Environment Result parse(struct Slice* slices) { - struct Slice* token = slices; - if (!token || !token->text) { - return (Result) { errorObject(NULL_PARSE), NULL }; - } + assert(slices); + assert(slices->text); + struct Slice* token = slices; struct Slice* rest = &slices[1]; if (token->text[0] == '\'' && token->text[1] == '(') { Result r = readSeq(&slices[2]); @@ -480,7 +473,7 @@ int decChar(char c) return -1; } -Object parseNum(int base, const char* text, int length, int (* func)(char)) +Object parseNum(int sign, int base, const char* text, int length, int (* func)(char)) { int num = 0; for (int i = 0; i < length; i++) { @@ -492,7 +485,7 @@ Object parseNum(int base, const char* text, int length, int (* func)(char)) num *= base; num += value; } - return numberObject(num); + return numberObject(num * sign); } Object optimize(Object (* func)(Object*, int, struct Environment*), int argCount, Object args[]) @@ -516,17 +509,24 @@ Object optimize(Object (* func)(Object*, int, struct Environment*), int argCount Result parseAtom(struct Slice* s) { - const char c = s->text[0]; - if (isDigit(c)) { + char c = s->text[0]; + if (isDigit(c) || (c == '-' && isDigit(s->text[1]))) { + int sign = 1; + if (c == '-') { + s->text = &s->text[1]; + s->length -= 1; + c = s->text[0]; + sign = -1; + } if (c != '0' || s->length == 1) { - return (Result) { parseNum(10, s->text, s->length, decChar), s }; + return (Result) { parseNum(sign, 10, s->text, s->length, decChar), s }; } #ifndef LOW_MEM if (s->text[1] == 'x') { - return (Result) { parseNum(16, s->text + 2, s->length - 2, hexChar), s }; + return (Result) { parseNum(sign, 16, s->text + 2, s->length - 2, hexChar), s }; } if (s->text[1] == 'b') { - return (Result) { parseNum(2, s->text + 2, s->length - 2, binChar), s }; + return (Result) { parseNum(sign, 2, s->text + 2, s->length - 2, binChar), s }; } #endif return (Result) { errorWithContext(UNSUPPORTED_NUMBER_TYPE, s->text), s }; diff --git a/src/plfunc/general.c b/src/plfunc/general.c index 6538951..6a66b3e 100644 --- a/src/plfunc/general.c +++ b/src/plfunc/general.c @@ -81,19 +81,13 @@ Object at(Object* params, unused int length, unused struct Environment* env) Object index = params[0]; Object list = params[1]; - const Object* found = NULL; int n = index.number; FOR_POINTER_IN_LIST(&list) { if (n-- == 0) { - found = POINTER; - break; + return cloneObject(*POINTER); } } - if (found) { - return cloneObject(*found); - } - throw(INDEX_PAST_END, "Tried to access index %ld from list of len %d", index.number, listLength(&list)); } @@ -298,7 +292,7 @@ Object equ(Object* params, int length, unused struct Environment* env) Object or(Object* params, int length, unused struct Environment* env) { if (length < 2) { - return errorObject(NOT_ENOUGH_ARGUMENTS); + throw(NOT_ENOUGH_ARGUMENTS, "`|` requires at least two arguments"); } for (int i = 0; i < length - 1; i++) { @@ -313,7 +307,7 @@ Object or(Object* params, int length, unused struct Environment* env) Object NAME(Object* params, int length, struct Environment* env) \ { \ if (length < 2) { \ - return errorObject(NOT_ENOUGH_ARGUMENTS); \ + throw(NOT_ENOUGH_ARGUMENTS, "`" # OP "` requires at least two arguments"); \ } \ \ for (int i = 0; i < length - 1; i++) { \