diff --git a/src/object.c b/src/object.c index f0692b9..de21cd2 100644 --- a/src/object.c +++ b/src/object.c @@ -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) { + if (!context) { + context = ""; + } char* copiedContext = malloc(sizeof(char) * ERR_LEN); strcpy(copiedContext, context); return errorWithAllocatedContextLineNo(code, copiedContext, lineNo, fileName); diff --git a/src/pebblisp.c b/src/pebblisp.c index 252b19d..8feeafe 100644 --- a/src/pebblisp.c +++ b/src/pebblisp.c @@ -328,24 +328,24 @@ Object structAccess(Object* params, unused int length, unused struct Environment Result parse(struct Slice* slices) { struct Slice* token = slices; - if (token && token->text) { - struct Slice* rest = &slices[1]; - if (token->text[0] == '\'' && token->text[1] == '(') { - Result r = readSeq(&slices[2]); - if (r.obj.type == TYPE_LIST) { - r.obj.type = TYPE_SLIST; - } - return r; - } else if (token->text[0] == '(') { - return readSeq(rest); - } else { - Result r = parseAtom(token); - r.slices = &r.slices[1]; - return r; - } - } else { + if (!token || !token->text) { return (Result) { errorObject(NULL_PARSE), NULL }; } + + struct Slice* rest = &slices[1]; + if (token->text[0] == '\'' && token->text[1] == '(') { + Result r = readSeq(&slices[2]); + if (r.obj.type == TYPE_LIST) { + r.obj.type = TYPE_SLIST; + } + return r; + } else if (token->text[0] == '(') { + return readSeq(rest); + } else { + Result r = parseAtom(token); + r.slices = &r.slices[1]; + return r; + } } #ifndef NO_SUGAR @@ -382,33 +382,47 @@ Result readSeq(struct Slice* tokens) } } -Object parseDecimal(struct Slice* s) +int hexChar(char c) { - int num = 0; - for (int i = 0; i < s->length; i++) { - if (!isDigit(s->text[i])) { - return errorObject(BAD_NUMBER); - } - num *= 10; - num += s->text[i] - '0'; + if (isDigit(c)) { + return c - '0'; } - return numberObject(num); + if (c >= 'a' && c <= 'f') { + return c - 'a' + 10; + } + 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; - for (int i = 2; i < s->length; i++) { - const char c = s->text[i]; - if (!isHex(c)) { - return errorObject(BAD_NUMBER); - } - num *= 16; - if (isDigit(c)) { - num += c - '0'; - } else /* is hex */ { - num += c - 'a' + 10; + for (int i = 0; i < length; i++) { + const char c = text[i]; + int value = func(c); + if (value < 0) { + throw(BAD_NUMBER, "at %s", text); } + num *= base; + num += value; } return numberObject(num); } @@ -440,30 +454,28 @@ Result parseAtom(struct Slice* s) const char c = s->text[0]; if (isDigit(c)) { if (c != '0' || s->length == 1) { - return (Result) { parseDecimal(s), s }; -#ifndef LOW_MEM - } else if (s->text[1] == 'x') { - return (Result) { parseHex(s), s }; - } else if (s->text[1] == 'b') { - return (Result) { parseBin(s), s }; -#endif - } else { - return (Result) { errorWithContext(UNSUPPORTED_NUMBER_TYPE, s->text), s }; + return (Result) { parseNum(10, s->text, s->length, decChar), s }; } - } else if (s->length == 1 && c == 'T') { +#ifndef LOW_MEM + if (s->text[1] == 'x') { + return (Result) { parseNum(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 }; + } +#endif + return (Result) { errorWithContext(UNSUPPORTED_NUMBER_TYPE, s->text), s }; + } + if (s->length == 1 && c == 'T') { return (Result) { trueObject(), s }; - } else if (s->length == 1 && c == 'F') { + } + if (s->length == 1 && c == 'F') { return (Result) { falseObject(), s }; - } else if (c == '"'/* || c == '\''*/) { + } + if (c == '"') { return (Result) { objFromSlice(s->text, s->length), s }; - } else 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); + } + if (s->text[s->length] == '.') { struct Slice* next = s + 2; f.arguments[1] = stringFromSlice(next->text, next->length); @@ -523,7 +535,7 @@ Object parseEval(const char* input, struct Environment* env) cleanObject(&obj); Object parsed = parse(tok).obj; if (parsed.type == TYPE_ERROR) { - obj = parsed; // TODO Check necessity + obj = parsed; #ifdef STANDALONE obj.error->plContext = malloc(sizeof(struct Slice)); *obj.error->plContext = *lastOpen; diff --git a/src/plfunc.c b/src/plfunc.c index 298f7fb..6561f64 100644 --- a/src/plfunc.c +++ b/src/plfunc.c @@ -107,7 +107,7 @@ Object at(Object* params, unused int length, unused struct Environment* env) 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) diff --git a/src/tokens.c b/src/tokens.c index e0a55bf..0c6433e 100644 --- a/src/tokens.c +++ b/src/tokens.c @@ -18,7 +18,7 @@ int isSingle(const char c) int i = 0; while (singleTokens[i] != '\0') { if (singleTokens[i] == c) { - return singleTokens[i]; + return 1; } i++; } @@ -30,11 +30,6 @@ int isDigit(const char c) return c >= '0' && c <= '9'; } -int isHex(const char c) -{ - return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'); -} - int isWhitespace(const char c) { return c == ' ' || c == '\t' || c == '\n';