/** * io/print.c * * Post Scarcity Software Environment: print. * * Print basic Lisp objects..This is :bootstrap layer print; it needs to be * able to print characters, symbols, integers, lists and dotted pairs. I * don't think it needs to be able to print anything else. * * (c) 2026 Simon Brooke * Licensed under GPL version 2.0, or, at your option, any later version. */ #include #include #include #include #include /* * wide characters */ #include #include /* libcurl, used for io */ #include #include "io/fopen.h" #include "io/io.h" #include "memory/node.h" #include "memory/pointer.h" #include "memory/pso.h" #include "memory/pso2.h" #include "memory/tags.h" #include "payloads/character.h" #include "payloads/cons.h" #include "payloads/integer.h" #include "ops/truth.h" struct pso_pointer in_print(struct pso_pointer p, URL_FILE *output); struct pso_pointer print_string_like_thing(struct pso_pointer p, URL_FILE *output) { switch (get_tag_value(p)) { case KEYTV: url_fputwc(L':', output); break; case STRINGTV: url_fputwc(L'"', output); break; } if (keywordp(p) || stringp(p) || symbolp(p)) { for (struct pso_pointer cursor = p; !nilp(cursor); cursor = pointer_to_object(cursor)->payload.string.cdr) { url_fputwc(pointer_to_object(cursor)->payload.character.character, output); } } if (stringp(p)) { url_fputwc(L'"', output); } } struct pso_pointer print_list_content(struct pso_pointer p, URL_FILE *output) { struct pso_pointer result = nil; if (consp(p)) { for (; consp(p); p = c_cdr(p)) { struct pso2 *object = pointer_to_object(p); result = in_print(object->payload.cons.car, output); if (exceptionp(result)) break; switch (get_tag_value(object->payload.cons.cdr)) { case NILTV: break; case CONSTV: url_fputwc(L' ', output); break; default: url_fputws(L" . ", output); result = in_print(object->payload.cons.cdr, output); } } } else { // TODO: return exception } return result; } struct pso_pointer in_print(struct pso_pointer p, URL_FILE *output) { struct pso2 *object = pointer_to_object(p); struct pso_pointer result = nil; if (object != NULL) { uint32_t v = get_tag_value(p); switch (v) { case CHARACTERTV: url_fputwc(object->payload.character.character, output); break; case CONSTV: url_fputwc(L'(', output); result = print_list_content(p, output); url_fputwc(L')', output); break; case INTEGERTV: url_fwprintf(output, L"%d", (int64_t)(object->payload.integer.value)); break; case KEYTV: case STRINGTV: case SYMBOLTV: print_string_like_thing(p, output); break; case NILTV: url_fputws(L"nil", output); break; case READTV: case WRITETV: url_fwprintf(output, L"<%s stream: ", v == READTV ? "read" : "write"); in_print(object->payload.stream.meta, output); url_fputwc(L'>', output); break; case TRUETV: url_fputwc(L't', output); break; default: // TODO: return exception } } else { // TODO: return exception } return result; } /** * @brief Simple print for bootstrap layer. * * @param p pointer to the object to print. * @param stream if a pointer to an open write stream, print to there. * @return struct pso_pointer `nil`, or an exception if some erroe occurred. */ struct pso_pointer c_print(struct pso_pointer p, struct pso_pointer stream) { struct pso_pointer result = p; URL_FILE *output = writep(stream) ? pointer_to_object(stream)->payload.stream.stream : file_to_url_file(stdout); if (writep(stream)) { inc_ref(stream); result = in_print(p, output); dec_ref(stream); } return result; }