diff options
author | Daniel Cerqueira <dan.git@lispclub.com> | 2025-05-29 13:24:39 +0100 |
---|---|---|
committer | Daniel Cerqueira <dan.git@lispclub.com> | 2025-05-29 13:24:39 +0100 |
commit | 4ca60176436134226d269a21e899a5fa3ae65e3d (patch) | |
tree | ca1ccbdd2c10b02d5eb0f8fc43d149ff76ed5367 /liblali.c | |
parent | f1fe930de080baede6951b2414c7631abe6b4860 (diff) |
make numbers neutral
Diffstat (limited to 'liblali.c')
-rw-r--r-- | liblali.c | 87 |
1 files changed, 65 insertions, 22 deletions
@@ -276,13 +276,13 @@ Object *newCons(Object **car, Object **cdr, GC_PARAM) { return object; } -Object *newSymbolWithLength(char *string, size_t length, GC_PARAM) { +Object *newSymbolWithLength(Type type, char *string, size_t length, GC_PARAM) { for (Object *object = symbols; object != nil; object = object->cdr) if (memcmp(object->car->string, string, length) == 0 && object->car->string[length] == '\0') return object->car; - GC_TRACE(gcObject, newObjectWithString(TYPE_SYMBOL, length + 1, GC_ROOTS)); + GC_TRACE(gcObject, newObjectWithString(type, length + 1, GC_ROOTS)); memcpy((*gcObject)->string, string, length); (*gcObject)->string[length] = '\0'; @@ -292,7 +292,7 @@ Object *newSymbolWithLength(char *string, size_t length, GC_PARAM) { } Object *newSymbol(char *string, GC_PARAM) { - return newSymbolWithLength(string, strlen(string), GC_ROOTS); + return newSymbolWithLength(TYPE_SYMBOL, string, strlen(string), GC_ROOTS); } Object *newObjectWithClosure(Type type, Object **params, Object **body, Object **env, GC_PARAM) { @@ -535,34 +535,73 @@ Object *readNumberOrSymbol(Stream *stream, GC_PARAM) { size_t offset = stream->offset; int ch = streamPeek(stream); - // skip optional leading sign + // numbers must have a leading sign if (ch == '+' || ch == '-') { streamGetc(stream); ch = streamPeek(stream); - } - // try to read a number in integer or decimal format - if (ch == '.' || isdigit(ch)) { - if (isdigit(ch)) - ch = readWhile(stream, isdigit); - if (!isSymbolChar(ch)) - return newNumber(strtol(stream->buffer + offset, NULL, 10), GC_ROOTS); - if (ch == '.') { - ch = streamGetc(stream); - if (isdigit(streamPeek(stream))) { + // try to read a number in integer or decimal format + if (ch == '.' || isdigit(ch)) { + if (isdigit(ch)) ch = readWhile(stream, isdigit); - if (!isSymbolChar(ch)) - return newNumber(strtod(stream->buffer + offset, NULL), GC_ROOTS); + if (!isSymbolChar(ch)) + return newSymbolWithLength(TYPE_NUMBER, stream->buffer + offset, + stream->offset - offset, GC_ROOTS); + if (ch == '.') { + ch = streamGetc(stream); + if (isdigit(streamPeek(stream))) { + ch = readWhile(stream, isdigit); + if (!isSymbolChar(ch)) + return newSymbolWithLength(TYPE_NUMBER, stream->buffer + offset, + stream->offset - offset, GC_ROOTS); + } } } } // non-numeric character encountered, read a symbol readWhile(stream, isSymbolChar); - return newSymbolWithLength(stream->buffer + offset, + return newSymbolWithLength(TYPE_SYMBOL, stream->buffer + offset, stream->offset - offset, GC_ROOTS); } +/* Object *readNumberOrSymbol(Stream *stream, GC_PARAM) { */ +/* size_t offset = stream->offset; */ +/* int ch = streamPeek(stream); */ + +/* // skip optional leading sign */ +/* /\* if (ch == '+' || ch == '-') { *\/ */ +/* /\* streamGetc(stream); *\/ */ +/* /\* ch = streamPeek(stream); *\/ */ +/* /\* } *\/ */ + +/* if (ch == '+' || ch == '-') { */ +/* streamGetc(stream); */ +/* ch = streamPeek(stream); */ + +/* // try to read a number in integer or decimal format */ +/* if (ch == '.' || isdigit(ch)) { */ +/* if (isdigit(ch)) */ +/* ch = readWhile(stream, isdigit); */ +/* if (!isSymbolChar(ch)) */ +/* return newNumber(strtol(stream->buffer + offset, NULL, 10), GC_ROOTS); */ +/* if (ch == '.') { */ +/* ch = streamGetc(stream); */ +/* if (isdigit(streamPeek(stream))) { */ +/* ch = readWhile(stream, isdigit); */ +/* if (!isSymbolChar(ch)) */ +/* return newNumber(strtod(stream->buffer + offset, NULL), GC_ROOTS); */ +/* } */ +/* } */ +/* } */ +/* } */ + +/* // non-numeric character encountered, read a symbol */ +/* readWhile(stream, isSymbolChar); */ +/* return newSymbolWithLength(stream->buffer + offset, */ +/* stream->offset - offset, GC_ROOTS); */ +/* } */ + Object *reverseList(Object *list) { Object *object = nil; @@ -637,7 +676,8 @@ void writeObject(Object *object, bool readably, FILE *file) { case type: \ fprintf(file, __VA_ARGS__); \ break - CASE(TYPE_NUMBER, "%g", object->number); + /* CASE(TYPE_NUMBER, (object->number < 0) ? "%g" : "+%g", object->number); */ + CASE(TYPE_NUMBER, "%s", object->string); CASE(TYPE_SYMBOL, "%s", object->string); CASE(TYPE_PRIMITIVE, "#<Primitive %s>", object->name); #undef CASE @@ -713,6 +753,9 @@ void writeObject(Object *object, bool readably, FILE *file) { */ Object *envLookup(Object *var, Object *env) { + if (var->type == TYPE_NUMBER) + return var; + for (; env != nil; env = env->parent) { Object *vars = env->vars, *vals = env->vals; @@ -784,9 +827,9 @@ Object *primitiveAtom(Object **args, GC_PARAM) { Object *primitiveDif(Object **args, GC_PARAM) { Object *first = (*args)->car, *second = (*args)->cdr->car; - if (first->type == TYPE_NUMBER && second->type == TYPE_NUMBER) - return (first->number != second->number) ? t : f; - else if (first->type == TYPE_STRING && second->type == TYPE_STRING) + /* if (first->type == TYPE_NUMBER && second->type == TYPE_NUMBER) */ + /* return (first->number != second->number) ? t : f; */ + if (first->type == TYPE_STRING && second->type == TYPE_STRING) return strcmp(first->string, second->string) ? t : f; else return (first != second) ? t : f; @@ -1275,7 +1318,7 @@ Object *evalExpr(Object **object, Object **env, GC_PARAM) { GC_TRACE(gcBody, nil); for (;;) { - if ((*gcObject)->type == TYPE_SYMBOL) + if ((*gcObject)->type == TYPE_SYMBOL || (*gcObject)->type == TYPE_NUMBER) return envLookup(*gcObject, *gcEnv); if ((*gcObject)->type != TYPE_CONS) return *gcObject; |