Fix no-context error-handling.

Centralize parts of number-parsing.
This commit is contained in:
Sage Vaillancourt 2022-04-14 16:04:17 -04:00 committed by Sage Vaillancourt
parent 3f4d8fd7af
commit 83b1b9212e
4 changed files with 74 additions and 64 deletions

View File

@ -824,6 +824,9 @@ errorWithAllocatedContextLineNo(enum errorCode code, char* context, int lineNo,
inline Object errorWithContextLineNo(enum errorCode code, const char* context, int lineNo, const char* fileName) inline Object errorWithContextLineNo(enum errorCode code, const char* context, int lineNo, const char* fileName)
{ {
if (!context) {
context = "";
}
char* copiedContext = malloc(sizeof(char) * ERR_LEN); char* copiedContext = malloc(sizeof(char) * ERR_LEN);
strcpy(copiedContext, context); strcpy(copiedContext, context);
return errorWithAllocatedContextLineNo(code, copiedContext, lineNo, fileName); return errorWithAllocatedContextLineNo(code, copiedContext, lineNo, fileName);

View File

@ -328,7 +328,10 @@ Object structAccess(Object* params, unused int length, unused struct Environment
Result parse(struct Slice* slices) Result parse(struct Slice* slices)
{ {
struct Slice* token = slices; struct Slice* token = slices;
if (token && token->text) { if (!token || !token->text) {
return (Result) { errorObject(NULL_PARSE), NULL };
}
struct Slice* rest = &slices[1]; struct Slice* rest = &slices[1];
if (token->text[0] == '\'' && token->text[1] == '(') { if (token->text[0] == '\'' && token->text[1] == '(') {
Result r = readSeq(&slices[2]); Result r = readSeq(&slices[2]);
@ -343,9 +346,6 @@ Result parse(struct Slice* slices)
r.slices = &r.slices[1]; r.slices = &r.slices[1];
return r; return r;
} }
} else {
return (Result) { errorObject(NULL_PARSE), NULL };
}
} }
#ifndef NO_SUGAR #ifndef NO_SUGAR
@ -382,33 +382,47 @@ Result readSeq(struct Slice* tokens)
} }
} }
Object parseDecimal(struct Slice* s) int hexChar(char c)
{ {
int num = 0; if (isDigit(c)) {
for (int i = 0; i < s->length; i++) { return c - '0';
if (!isDigit(s->text[i])) {
return errorObject(BAD_NUMBER);
} }
num *= 10; if (c >= 'a' && c <= 'f') {
num += s->text[i] - '0'; return c - 'a' + 10;
} }
return numberObject(num); if (c >= 'A' && c <= 'F'){
return c - 'A' + 10;
}
return -1;
} }
Object parseHex(struct Slice* s) int binChar(char c)
{
if (c == '0' || c == '1') {
return c - '0';
}
return -1;
}
int decChar(char c)
{
if (isDigit(c)) {
return c - '0';
}
return -1;
}
Object parseNum(int base, const char* text, int length, int (*func)(char))
{ {
int num = 0; int num = 0;
for (int i = 2; i < s->length; i++) { for (int i = 0; i < length; i++) {
const char c = s->text[i]; const char c = text[i];
if (!isHex(c)) { int value = func(c);
return errorObject(BAD_NUMBER); if (value < 0) {
} throw(BAD_NUMBER, "at %s", text);
num *= 16;
if (isDigit(c)) {
num += c - '0';
} else /* is hex */ {
num += c - 'a' + 10;
} }
num *= base;
num += value;
} }
return numberObject(num); return numberObject(num);
} }
@ -440,30 +454,28 @@ Result parseAtom(struct Slice* s)
const char c = s->text[0]; const char c = s->text[0];
if (isDigit(c)) { if (isDigit(c)) {
if (c != '0' || s->length == 1) { if (c != '0' || s->length == 1) {
return (Result) { parseDecimal(s), s }; return (Result) { parseNum(10, s->text, s->length, decChar), s };
}
#ifndef LOW_MEM #ifndef LOW_MEM
} else if (s->text[1] == 'x') { if (s->text[1] == 'x') {
return (Result) { parseHex(s), s }; return (Result) { parseNum(16, s->text + 2, s->length - 2, hexChar), s };
} else if (s->text[1] == 'b') { }
return (Result) { parseBin(s), s }; if (s->text[1] == 'b') {
return (Result) { parseNum(2, s->text + 2, s->length - 2, binChar), s };
}
#endif #endif
} else {
return (Result) { errorWithContext(UNSUPPORTED_NUMBER_TYPE, s->text), s }; return (Result) { errorWithContext(UNSUPPORTED_NUMBER_TYPE, s->text), s };
} }
} else if (s->length == 1 && c == 'T') { if (s->length == 1 && c == 'T') {
return (Result) { trueObject(), s }; return (Result) { trueObject(), s };
} else if (s->length == 1 && c == 'F') { }
if (s->length == 1 && c == 'F') {
return (Result) { falseObject(), s }; return (Result) { falseObject(), s };
} else if (c == '"'/* || c == '\''*/) { }
if (c == '"') {
return (Result) { objFromSlice(s->text, s->length), s }; return (Result) { objFromSlice(s->text, s->length), s };
} else if (s->text[s->length] == '.') { }
/* if (s->text[s->length] == '.') {
struct InlinedFunction f ={
.func = structAccess,
.arguments = malloc(sizeof(Object) * 2),
.argCount = 2,
};
f.arguments[0] = symFromSlice(s->text, s->length);
struct Slice* next = s + 2; struct Slice* next = s + 2;
f.arguments[1] = stringFromSlice(next->text, next->length); f.arguments[1] = stringFromSlice(next->text, next->length);
@ -523,7 +535,7 @@ Object parseEval(const char* input, struct Environment* env)
cleanObject(&obj); cleanObject(&obj);
Object parsed = parse(tok).obj; Object parsed = parse(tok).obj;
if (parsed.type == TYPE_ERROR) { if (parsed.type == TYPE_ERROR) {
obj = parsed; // TODO Check necessity obj = parsed;
#ifdef STANDALONE #ifdef STANDALONE
obj.error->plContext = malloc(sizeof(struct Slice)); obj.error->plContext = malloc(sizeof(struct Slice));
*obj.error->plContext = *lastOpen; *obj.error->plContext = *lastOpen;

View File

@ -107,7 +107,7 @@ Object at(Object* params, unused int length, unused struct Environment* env)
return cloneObject(*found); return cloneObject(*found);
} }
return errorObject(INDEX_PAST_END); throw(INDEX_PAST_END, "Tried to access index %ld from list of len %d", index.number, listLength(&list));
} }
Object rest(Object* params, unused int length, unused struct Environment* env) Object rest(Object* params, unused int length, unused struct Environment* env)

View File

@ -18,7 +18,7 @@ int isSingle(const char c)
int i = 0; int i = 0;
while (singleTokens[i] != '\0') { while (singleTokens[i] != '\0') {
if (singleTokens[i] == c) { if (singleTokens[i] == c) {
return singleTokens[i]; return 1;
} }
i++; i++;
} }
@ -30,11 +30,6 @@ int isDigit(const char c)
return c >= '0' && c <= '9'; return c >= '0' && c <= '9';
} }
int isHex(const char c)
{
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
}
int isWhitespace(const char c) int isWhitespace(const char c)
{ {
return c == ' ' || c == '\t' || c == '\n'; return c == ' ' || c == '\t' || c == '\n';