Add a simple assert() macro.
assert() is disabled when calling make release Support negative numbers!
This commit is contained in:
parent
5ab7a638af
commit
139e912548
|
@ -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
|
||||
|
|
20
src/hash.c
20
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)
|
||||
|
|
18
src/main.c
18
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);
|
||||
}
|
||||
|
||||
|
|
11
src/object.c
11
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++) {
|
||||
|
|
|
@ -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("\n[31;1massertion '" # __VA_ARGS__ "' at %s:%d failed!\nBailing![0m\n", __FILE__, __LINE__); int* X = NULL; unused int Y = *X;}} while (0)
|
||||
#endif
|
||||
|
||||
#define MAX_TOK_CNT 2048
|
||||
|
||||
#define FOR_POINTER_IN_LIST(_list) \
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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++) { \
|
||||
|
|
Loading…
Reference in New Issue