From a210631a55c97b64125b28ecc4bbffdc8a3bfe5f Mon Sep 17 00:00:00 2001 From: Federico Angelilli Date: Thu, 6 Jun 2024 00:04:14 +0200 Subject: Refactor any_sexp --- any_sexp.h | 552 +++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 296 insertions(+), 256 deletions(-) (limited to 'any_sexp.h') diff --git a/any_sexp.h b/any_sexp.h index bbb186f..b36689f 100644 --- a/any_sexp.h +++ b/any_sexp.h @@ -3,8 +3,9 @@ // A single-file library that provides a simple and somewhat opinionated // interface for parsing and manipulating s-expressions. // -// Note that the library does not offer anything that can evaluate the -// s-expressions, but that can be easily implemented separately. +// Note that the library does not offer the means to evaluate the +// s-expressions. That can be easily implemented separately using the +// provided any_sexp_t type and helper functions. // // To use this library you should choose a suitable file to put the // implementation and define ANY_SEXP_IMPLEMENT. For example @@ -28,21 +29,21 @@ #include typedef enum { - ANY_SEXP_TAG_ERROR = 0xf, - ANY_SEXP_TAG_NIL = 0, - ANY_SEXP_TAG_CONS = 1 << 0, - ANY_SEXP_TAG_SYMBOL = 1 << 1, - ANY_SEXP_TAG_STRING = 1 << 2, + ANY_SEXP_TAG_ERROR = 0xf, + ANY_SEXP_TAG_NIL = 0, + ANY_SEXP_TAG_CONS = 1 << 0, + ANY_SEXP_TAG_SYMBOL = 1 << 1, + ANY_SEXP_TAG_STRING = 1 << 2, } any_sexp_tag_t; #ifdef ANY_SEXP_NO_BOXING typedef struct any_sexp { - any_sexp_tag_t tag; - union { - struct any_sexp_cons *cons; - char *symbol; - }; + any_sexp_tag_t tag; + union { + struct any_sexp_cons *cons; + char *symbol; + }; } any_sexp_t; #define ANY_SEXP_ERROR (any_sexp_error()) @@ -76,44 +77,62 @@ typedef void *any_sexp_t; #define ANY_SEXP_IS_NIL(sexp) (ANY_SEXP_IS_TAG(sexp, ANY_SEXP_TAG_NIL)) #define ANY_SEXP_IS_CONS(sexp) (ANY_SEXP_IS_TAG(sexp, ANY_SEXP_TAG_CONS)) -// NOTE: Use it only after checking the tag! #define ANY_SEXP_GET_CAR(sexp) (ANY_SEXP_GET_CONS(sexp)->car) #define ANY_SEXP_GET_CDR(sexp) (ANY_SEXP_GET_CONS(sexp)->cdr) typedef struct any_sexp_cons { - any_sexp_t car; - any_sexp_t cdr; + any_sexp_t car; + any_sexp_t cdr; } any_sexp_cons_t; -#ifndef ANY_SEXP_BUFFER_SIZE -#define ANY_SEXP_BUFFER_SIZE 512 -#endif - typedef char (*any_sexp_getchar_t)(void *stream); typedef int (*any_sexp_fprintf_t)(void *stream, const char *format, ...); +#ifndef ANY_SEXP_NO_READER + +#ifndef ANY_SEXP_READER_BUFFER_LENGTH +#define ANY_SEXP_READER_BUFFER_LENGTH 512 +#endif + +typedef struct { + any_sexp_getchar_t getc; + void *stream; + char c; +} any_sexp_reader_t; + typedef struct { - const char *source; - size_t length; - size_t cursor; -} any_sexp_string_stream_t; + const char *source; + size_t length; + size_t cursor; +} any_sexp_reader_string_t; + +void any_sexp_reader_init(any_sexp_reader_t *reader, any_sexp_getchar_t getc, void *stream); -char any_sexp_string_getc(any_sexp_string_stream_t *stream); +void any_sexp_reader_string_init(any_sexp_reader_t *reader, any_sexp_reader_string_t *string, const char *source, size_t length); + +bool any_sexp_reader_end(any_sexp_reader_t *reader); + +any_sexp_t any_sexp_read(any_sexp_reader_t *reader); + +#endif + +#ifndef ANY_SEXP_NO_WRITER typedef struct { - any_sexp_getchar_t getc; - void *stream; - char c; -} any_sexp_parser_t; + any_sexp_fprintf_t fprintf; + void *stream; +} any_sexp_writer_t; + +void any_sexp_writer_init(any_sexp_writer_t *writer, any_sexp_fprintf_t fprintf, void *stream); -void any_sexp_parser_init(any_sexp_parser_t *parser, any_sexp_getchar_t getc, void *stream); +int any_sexp_write(any_sexp_writer_t *writer, any_sexp_t sexp); -void any_sexp_parser_init_string(any_sexp_parser_t *parser, any_sexp_string_stream_t *stream, const char *source, size_t length); +int any_sexp_fprint(any_sexp_t sexp, FILE *file); -bool any_sexp_parser_eof(any_sexp_parser_t *parser); +int any_sexp_print(any_sexp_t sexp); -any_sexp_t any_sexp_parser_next(any_sexp_parser_t *parser); +#endif any_sexp_t any_sexp_error(void); @@ -133,12 +152,6 @@ any_sexp_t any_sexp_cdr(any_sexp_t sexp); any_sexp_t any_sexp_reverse(any_sexp_t sexp); -int any_sexp_stream_print(any_sexp_t sexp, any_sexp_fprintf_t fprintf, void *stream); - -int any_sexp_fprint(any_sexp_t sexp, FILE *file); - -int any_sexp_print(any_sexp_t sexp); - void any_sexp_free(any_sexp_t sexp); #endif @@ -181,342 +194,369 @@ void any_sexp_free(any_sexp_t sexp); #define ANY_SEXP_QUOTE_SYMBOL "quote" #endif -// Extended alphabetic characters -// ! $ % & * + - . / : < = > ? @ ^ _ ~ +#ifndef ANY_SEXP_NO_READER + +// For the scheme specification these are the extended characters +// to be accepted in addition to the alphanumeric ones in a symbol. +// ! $ % & * + - . / : < = > ? @ ^ _ ~ +// +// However here we allow any character except the ones used by +// other syntactic constructs. // static inline bool any_sexp_issym(char c) { - switch (c) { - case '!': case '$': case '%': - case '&': case '*': case '+': - case '-': case '.': case '/': - case ':': case '<': case '=': - case '>': case '?': case '@': - case '^': case '_': case '~': - - case '|': // TODO: Multiword symbols (CL) - return true; - - default: - return isalnum(c); - } +#ifndef ANY_SEXP_NO_COMMENT + if (c == ANY_SEXP_CHAR_COMMENT) + return false; +#endif + +#ifndef ANY_SEXP_NO_STRING + if (c == ANY_SEXP_CHAR_STRING) + return false; +#endif + +#ifndef ANY_SEXP_NO_QUOTE + if (c == ANY_SEXP_CHAR_QUOTE) + return false; +#endif + + if (c == ANY_SEXP_CHAR_QUOTE) + return false; + + return c != EOF + && c != ANY_SEXP_CHAR_OPEN + && c != ANY_SEXP_CHAR_CLOSE + && !isspace(c); } -static inline char any_sexp_parser_advance(any_sexp_parser_t *parser) +static inline char any_sexp_reader_advance(any_sexp_reader_t *reader) { - parser->c = parser->getc(parser->stream); - return parser->c; + reader->c = reader->getc(reader->stream); + return reader->c; } -static void any_sexp_parser_skip(any_sexp_parser_t *parser) +static void any_sexp_reader_skip(any_sexp_reader_t *reader) { - while (!any_sexp_parser_eof(parser)) { + while (!any_sexp_reader_end(reader)) { #ifndef ANY_SEXP_NO_COMMENT - if (parser->c == ANY_SEXP_CHAR_COMMENT) { - while (!any_sexp_parser_eof(parser) && parser->c != '\n') - any_sexp_parser_advance(parser); - } + if (reader->c == ANY_SEXP_CHAR_COMMENT) { + while (!any_sexp_reader_end(reader) && reader->c != '\n') + any_sexp_reader_advance(reader); + } #endif - if (!isspace(parser->c)) - return; + if (!isspace(reader->c)) + return; + + any_sexp_reader_advance(reader); + } +} - any_sexp_parser_advance(parser); - } +static char any_sexp_reader_string_getc(any_sexp_reader_string_t *string) +{ + if (string->cursor >= string->length) + return EOF; + return string->source[string->cursor++]; } -void any_sexp_parser_init(any_sexp_parser_t *parser, any_sexp_getchar_t getc, void *stream) +void any_sexp_reader_init(any_sexp_reader_t *reader, any_sexp_getchar_t getc, void *stream) { - parser->getc = getc; - parser->stream = stream; - any_sexp_parser_advance(parser); + reader->getc = getc; + reader->stream = stream; + any_sexp_reader_advance(reader); } -void any_sexp_parser_init_string(any_sexp_parser_t *parser, any_sexp_string_stream_t *stream, const char *source, size_t length) +void any_sexp_reader_string_init(any_sexp_reader_t *reader, any_sexp_reader_string_t *string, const char *source, size_t length) { - stream->source = source; - stream->length = length; - stream->cursor = 0; - any_sexp_parser_init(parser, (any_sexp_getchar_t)any_sexp_string_getc, stream); + string->source = source; + string->length = length; + string->cursor = 0; + any_sexp_reader_init(reader, (any_sexp_getchar_t)any_sexp_reader_string_getc, string); } -bool any_sexp_parser_eof(any_sexp_parser_t *parser) +bool any_sexp_reader_end(any_sexp_reader_t *reader) { - return parser->c == EOF; + return reader->c == EOF; } -any_sexp_t any_sexp_parser_next(any_sexp_parser_t *parser) +any_sexp_t any_sexp_read(any_sexp_reader_t *reader) { - char buffer[ANY_SEXP_BUFFER_SIZE + 1]; + char buffer[ANY_SEXP_READER_BUFFER_LENGTH + 1]; - any_sexp_parser_skip(parser); + any_sexp_reader_skip(reader); - // Symbol - if (any_sexp_issym(parser->c)) { - size_t length = 0; + // Symbol + if (any_sexp_issym(reader->c)) { + size_t length = 0; - do { - if (length < ANY_SEXP_BUFFER_SIZE) - buffer[length++] = parser->c; + do { + if (length < ANY_SEXP_READER_BUFFER_LENGTH) + buffer[length++] = reader->c; - any_sexp_parser_advance(parser); - } while (any_sexp_issym(parser->c)); + any_sexp_reader_advance(reader); + } while (any_sexp_issym(reader->c)); - return any_sexp_symbol(buffer, length); - } + return any_sexp_symbol(buffer, length); + } #ifndef ANY_SEXP_NO_STRING - // String - if (parser->c == ANY_SEXP_CHAR_STRING) { - any_sexp_parser_advance(parser); + // String + if (reader->c == ANY_SEXP_CHAR_STRING) { + any_sexp_reader_advance(reader); - size_t length = 0; - char prev = '\0'; + size_t length = 0; + char prev = '\0'; - while (!any_sexp_parser_eof(parser)) { - if (parser->c == ANY_SEXP_CHAR_STRING && prev != ANY_SEXP_CHAR_ESCAPE) - break; + while (!any_sexp_reader_end(reader)) { + if (reader->c == ANY_SEXP_CHAR_STRING && prev != ANY_SEXP_CHAR_ESCAPE) + break; - if (length < ANY_SEXP_BUFFER_SIZE) - buffer[length++] = parser->c; + if (length < ANY_SEXP_READER_BUFFER_LENGTH) + buffer[length++] = reader->c; - prev = parser->c; - any_sexp_parser_advance(parser); - } + prev = reader->c; + any_sexp_reader_advance(reader); + } - any_sexp_parser_advance(parser); - return any_sexp_string(buffer, length); - } + any_sexp_reader_advance(reader); + return any_sexp_string(buffer, length); + } #endif #ifndef ANY_SEXP_NO_QUOTE - // Quote - if (parser->c == ANY_SEXP_CHAR_QUOTE) { - any_sexp_parser_advance(parser); - return any_sexp_quote(any_sexp_parser_next(parser)); - } + // Quote + if (reader->c == ANY_SEXP_CHAR_QUOTE) { + any_sexp_reader_advance(reader); + return any_sexp_quote(any_sexp_read(reader)); + } #endif - // List - if (parser->c == ANY_SEXP_CHAR_OPEN) { - any_sexp_parser_advance(parser); + // List + if (reader->c == ANY_SEXP_CHAR_OPEN) { + any_sexp_reader_advance(reader); + + any_sexp_t sexp = ANY_SEXP_NIL; + + while (!any_sexp_reader_end(reader)) { + any_sexp_reader_skip(reader); + + if (reader->c == ANY_SEXP_CHAR_CLOSE) + break; - any_sexp_t sexp = ANY_SEXP_NIL; + any_sexp_t sub = any_sexp_read(reader); + sexp = any_sexp_cons(sub, sexp); // reversed - while (!any_sexp_parser_eof(parser)) { - any_sexp_parser_skip(parser); + if (ANY_SEXP_IS_ERROR(sub) || ANY_SEXP_IS_ERROR(sexp)) { + any_sexp_free(sexp); + return ANY_SEXP_ERROR; + } + } - if (parser->c == ANY_SEXP_CHAR_CLOSE) - break; + any_sexp_reader_advance(reader); + return any_sexp_reverse(sexp); + } - any_sexp_t sub = any_sexp_parser_next(parser); - sexp = any_sexp_cons(sub, sexp); // reversed + return ANY_SEXP_ERROR; +} - if (ANY_SEXP_IS_ERROR(sub) || ANY_SEXP_IS_ERROR(sexp)) { - any_sexp_free(sexp); - return ANY_SEXP_ERROR; - } - } +#endif - any_sexp_parser_advance(parser); - return any_sexp_reverse(sexp); - } +#ifndef ANY_SEXP_NO_WRITER - return ANY_SEXP_ERROR; +void any_sexp_writer_init(any_sexp_writer_t *writer, any_sexp_fprintf_t fprintf, void *stream) +{ + writer->fprintf = fprintf; + writer->stream = stream; } -char any_sexp_string_getc(any_sexp_string_stream_t *stream) +int any_sexp_write(any_sexp_writer_t *writer, any_sexp_t sexp) { - if (stream->cursor >= stream->length) - return EOF; + switch (ANY_SEXP_GET_TAG(sexp)) { + case ANY_SEXP_TAG_ERROR: + return writer->fprintf(writer->stream, ""); + + case ANY_SEXP_TAG_NIL: + return writer->fprintf(writer->stream, "()"); + + case ANY_SEXP_TAG_CONS: { + int c = writer->fprintf(writer->stream, "("); + while (!ANY_SEXP_IS_NIL(sexp) && !ANY_SEXP_IS_ERROR(sexp)) { + c += any_sexp_write(writer, any_sexp_car(sexp)); + sexp = any_sexp_cdr(sexp); + + if (!ANY_SEXP_IS_NIL(sexp)) + c += writer->fprintf(writer->stream, " "); + } + c += writer->fprintf(writer->stream, ")"); + return c; + } + + case ANY_SEXP_TAG_SYMBOL: + return writer->fprintf(writer->stream, "%s", ANY_SEXP_GET_SYMBOL(sexp)); + + case ANY_SEXP_TAG_STRING: + return writer->fprintf(writer->stream, "\"%s\"", ANY_SEXP_GET_STRING(sexp)); + } +} - return stream->source[stream->cursor++]; +int any_sexp_fprint(any_sexp_t sexp, FILE *file) +{ + any_sexp_writer_t writer; + any_sexp_writer_init(&writer, (any_sexp_fprintf_t)fprintf, file); + return any_sexp_write(&writer, sexp); } +int any_sexp_print(any_sexp_t sexp) +{ + return any_sexp_fprint(sexp, stdout); +} + +#endif + any_sexp_t any_sexp_error(void) { #ifndef ANY_SEXP_NO_BOXING - return ANY_SEXP_ERROR; + return ANY_SEXP_ERROR; #else - any_sexp_t sexp = { - .tag = ANY_SEXP_TAG_ERROR, - }; - return sexp; + any_sexp_t sexp = { + .tag = ANY_SEXP_TAG_ERROR, + }; + return sexp; #endif } any_sexp_t any_sexp_nil(void) { #ifndef ANY_SEXP_NO_BOXING - return ANY_SEXP_NIL; + return ANY_SEXP_NIL; #else - any_sexp_t sexp = { - .tag = ANY_SEXP_TAG_NIL, - }; - return sexp; + any_sexp_t sexp = { + .tag = ANY_SEXP_TAG_NIL, + }; + return sexp; #endif } any_sexp_t any_sexp_symbol(char *symbol, size_t length) { - any_sexp_t sexp = any_sexp_string(symbol, length); - if (ANY_SEXP_IS_ERROR(sexp)) - return ANY_SEXP_ERROR; + any_sexp_t sexp = any_sexp_string(symbol, length); + if (ANY_SEXP_IS_ERROR(sexp)) + return ANY_SEXP_ERROR; - // Override tag + // Override tag #ifndef ANY_SEXP_NO_BOXING - return ANY_SEXP_TAG(ANY_SEXP_UNTAG(sexp), ANY_SEXP_TAG_SYMBOL); + return ANY_SEXP_TAG(ANY_SEXP_UNTAG(sexp), ANY_SEXP_TAG_SYMBOL); #else - sexp.tag = ANY_SEXP_TAG_SYMBOL; - return sexp; + sexp.tag = ANY_SEXP_TAG_SYMBOL; + return sexp; #endif } any_sexp_t any_sexp_string(char *string, size_t length) { - if (string == NULL) - return ANY_SEXP_ERROR; + if (string == NULL) + return ANY_SEXP_ERROR; - char *copy = ANY_SEXP_MALLOC(length + 1); - if (copy == NULL) - return ANY_SEXP_ERROR; + char *copy = ANY_SEXP_MALLOC(length + 1); + if (copy == NULL) + return ANY_SEXP_ERROR; - memcpy(copy, string, length); - copy[length] = '\0'; + memcpy(copy, string, length); + copy[length] = '\0'; #ifndef ANY_SEXP_NO_BOXING - return ANY_SEXP_TAG(copy, ANY_SEXP_TAG_STRING); + return ANY_SEXP_TAG(copy, ANY_SEXP_TAG_STRING); #else - any_sexp_t sexp = { - .tag = ANY_SEXP_TAG_STRING, - .symbol = copy, - }; - return sexp; + any_sexp_t sexp = { + .tag = ANY_SEXP_TAG_STRING, + .symbol = copy, + }; + return sexp; #endif } any_sexp_t any_sexp_quote(any_sexp_t sexp) { - any_sexp_t quote = any_sexp_symbol(ANY_SEXP_QUOTE_SYMBOL, strlen(ANY_SEXP_QUOTE_SYMBOL)); - return any_sexp_cons(quote, any_sexp_cons(sexp, ANY_SEXP_NIL)); + any_sexp_t quote = any_sexp_symbol(ANY_SEXP_QUOTE_SYMBOL, strlen(ANY_SEXP_QUOTE_SYMBOL)); + return any_sexp_cons(quote, any_sexp_cons(sexp, ANY_SEXP_NIL)); } any_sexp_t any_sexp_cons(any_sexp_t car, any_sexp_t cdr) { - any_sexp_cons_t *cons = ANY_SEXP_MALLOC(sizeof(any_sexp_cons_t)); - if (cons == NULL) - return ANY_SEXP_ERROR; + any_sexp_cons_t *cons = ANY_SEXP_MALLOC(sizeof(any_sexp_cons_t)); + if (cons == NULL) + return ANY_SEXP_ERROR; - cons->car = car; - cons->cdr = cdr; + cons->car = car; + cons->cdr = cdr; #ifndef ANY_SEXP_NO_BOXING - return ANY_SEXP_TAG(cons, ANY_SEXP_TAG_CONS); + return ANY_SEXP_TAG(cons, ANY_SEXP_TAG_CONS); #else - any_sexp_t sexp = { - .tag = ANY_SEXP_TAG_CONS, - .cons = cons, - }; - return sexp; + any_sexp_t sexp = { + .tag = ANY_SEXP_TAG_CONS, + .cons = cons, + }; + return sexp; #endif } any_sexp_t any_sexp_car(any_sexp_t sexp) { - if (!ANY_SEXP_IS_CONS(sexp)) - return ANY_SEXP_ERROR; - return ANY_SEXP_GET_CAR(sexp); + if (!ANY_SEXP_IS_CONS(sexp)) + return ANY_SEXP_ERROR; + return ANY_SEXP_GET_CAR(sexp); } any_sexp_t any_sexp_cdr(any_sexp_t sexp) { - if (!ANY_SEXP_IS_CONS(sexp)) - return ANY_SEXP_ERROR; - return ANY_SEXP_GET_CDR(sexp); + if (!ANY_SEXP_IS_CONS(sexp)) + return ANY_SEXP_ERROR; + return ANY_SEXP_GET_CDR(sexp); } any_sexp_t any_sexp_reverse(any_sexp_t sexp) { - if (ANY_SEXP_IS_NIL(sexp)) - return sexp; + if (ANY_SEXP_IS_NIL(sexp)) + return sexp; - if (!ANY_SEXP_IS_CONS(sexp)) - return ANY_SEXP_ERROR; + if (!ANY_SEXP_IS_CONS(sexp)) + return ANY_SEXP_ERROR; - any_sexp_t cons = sexp, - prev = ANY_SEXP_NIL, - next = ANY_SEXP_NIL; + any_sexp_t cons = sexp, + prev = ANY_SEXP_NIL, + next = ANY_SEXP_NIL; - while (ANY_SEXP_GET_CONS(cons) != NULL) { - if (!ANY_SEXP_IS_NIL(cons) && !ANY_SEXP_IS_CONS(cons)) - return ANY_SEXP_ERROR; + while (ANY_SEXP_GET_CONS(cons) != NULL) { + if (!ANY_SEXP_IS_NIL(cons) && !ANY_SEXP_IS_CONS(cons)) + return ANY_SEXP_ERROR; - memcpy(&next, &ANY_SEXP_GET_CDR(cons), sizeof(any_sexp_t)); - memcpy(&ANY_SEXP_GET_CDR(cons), &prev, sizeof(any_sexp_t)); - memcpy(&prev, &cons, sizeof(any_sexp_t)); - memcpy(&cons, &next, sizeof(any_sexp_t)); - } + memcpy(&next, &ANY_SEXP_GET_CDR(cons), sizeof(any_sexp_t)); + memcpy(&ANY_SEXP_GET_CDR(cons), &prev, sizeof(any_sexp_t)); + memcpy(&prev, &cons, sizeof(any_sexp_t)); + memcpy(&cons, &next, sizeof(any_sexp_t)); + } - return prev; -} - -int any_sexp_stream_print(any_sexp_t sexp, any_sexp_fprintf_t fprintf, void *stream) -{ - int c = 0; - switch (ANY_SEXP_GET_TAG(sexp)) { - case ANY_SEXP_TAG_ERROR: - return fprintf(stream, ""); - - case ANY_SEXP_TAG_NIL: - return fprintf(stream, "()"); - - case ANY_SEXP_TAG_CONS: - c += fprintf(stream, "("); - while (!ANY_SEXP_IS_NIL(sexp) && !ANY_SEXP_IS_ERROR(sexp)) { - c += any_sexp_stream_print(any_sexp_car(sexp), fprintf, stream); - sexp = any_sexp_cdr(sexp); - - if (!ANY_SEXP_IS_NIL(sexp)) - c += fprintf(stream, " "); - } - c += fprintf(stream, ")"); - return c; - - case ANY_SEXP_TAG_SYMBOL: - return fprintf(stream, "%s", ANY_SEXP_GET_SYMBOL(sexp)); - - case ANY_SEXP_TAG_STRING: - return fprintf(stream, "\"%s\"", ANY_SEXP_GET_STRING(sexp)); - } -} - -int any_sexp_fprint(any_sexp_t sexp, FILE *file) -{ - return any_sexp_stream_print(sexp, (any_sexp_fprintf_t)fprintf, file); -} - -int any_sexp_print(any_sexp_t sexp) -{ - return any_sexp_fprint(sexp, stdout); + return prev; } void any_sexp_free(any_sexp_t sexp) { - switch (ANY_SEXP_GET_TAG(sexp)) { - case ANY_SEXP_TAG_NIL: - case ANY_SEXP_TAG_ERROR: - break; - - case ANY_SEXP_TAG_CONS: - any_sexp_free(any_sexp_car(sexp)); - any_sexp_free(any_sexp_cdr(sexp)); - ANY_SEXP_FREE(ANY_SEXP_GET_CONS(sexp)); - break; - - case ANY_SEXP_TAG_SYMBOL: - case ANY_SEXP_TAG_STRING: - ANY_SEXP_FREE(ANY_SEXP_GET_SYMBOL(sexp)); - break; - } + switch (ANY_SEXP_GET_TAG(sexp)) { + case ANY_SEXP_TAG_NIL: + case ANY_SEXP_TAG_ERROR: + break; + + case ANY_SEXP_TAG_CONS: + any_sexp_free(any_sexp_car(sexp)); + any_sexp_free(any_sexp_cdr(sexp)); + ANY_SEXP_FREE(ANY_SEXP_GET_CONS(sexp)); + break; + + case ANY_SEXP_TAG_SYMBOL: + case ANY_SEXP_TAG_STRING: + ANY_SEXP_FREE(ANY_SEXP_GET_SYMBOL(sexp)); + break; + } } #endif -- cgit v1.2.3