/src/print.c

https://github.com/fufu/wisp · C · 279 lines · 266 code · 12 blank · 1 comment · 11 complexity · 9b8c4984a77ed34d984fb40bc8e942ed MD5 · raw file

  1. #include "wisp.h"
  2. #include "print.h"
  3. void internal_generic_output(FILE* fp, CELL cell, int strict, int tab);
  4. void internal_print_env(FILE* fp, CELL env)
  5. {
  6. fputc('[', fp);
  7. while(ENVP(env)) {
  8. ENV* p = GET_ENV(env);
  9. int i;
  10. fputc('{', fp);
  11. for(i = 0; i < p->count; ++i) {
  12. if (i > 0) fprintf(fp, ", ");
  13. fprintf(fp, "#%d=", p->depth + i);
  14. internal_generic_output(fp, p->cells[i], 1, 0);
  15. }
  16. fputc('}', fp);
  17. env = p->next;
  18. if (ENVP(env)) fputc(';', fp);
  19. }
  20. fputc(']', fp);
  21. }
  22. void internal_generic_output(FILE* fp, CELL cell, int strict, int tab)
  23. {
  24. switch(GET_TYPE(cell)) {
  25. case T_VOID:
  26. fputs("#<void>", fp);
  27. break;
  28. case T_NULL:
  29. fputs("()", fp);
  30. break;
  31. case T_UNDEFINED:
  32. fputs("#<undefined>", fp);
  33. break;
  34. case T_EMPTY:
  35. fputs("#<empty>", fp);
  36. break;
  37. case T_BOOL:
  38. fputs(GET_BOOL(cell) ? "#t" : "#f", fp);
  39. break;
  40. case T_CHAR:
  41. {
  42. CHAR ch = GET_CHAR(cell);
  43. if (strict) {
  44. switch(ch) {
  45. case ' ': fputs("#\\space", fp); break;
  46. case 0: fputs("#\\nul", fp); break;
  47. case 27: fputs("#\\escape", fp); break;
  48. case 127: fputs("#\\rubout", fp); break;
  49. case '\a': fputs("#\\alarm", fp); break;
  50. case '\b': fputs("#\\backspace", fp); break;
  51. case '\f': fputs("#\\page", fp); break;
  52. case '\n': fputs("#\\newline", fp); break;
  53. case '\r': fputs("#\\return", fp); break;
  54. case '\t': fputs("#\\tab", fp); break;
  55. case '\v': fputs("#\\vtab", fp); break;
  56. default: fprintf(fp, "#\\%c", ch); break;
  57. }
  58. }
  59. else {
  60. fputc(ch, fp);
  61. }
  62. }
  63. break;
  64. case T_INT:
  65. fprintf(fp, "%d", GET_INT(cell));
  66. break;
  67. case T_BIGINT:
  68. fprintf(fp, "%lld", GET_BIGINT(cell));
  69. break;
  70. case T_FLOAT:
  71. fprintf(fp, "%f", GET_FLOAT(cell));
  72. break;
  73. case T_STRING:
  74. {
  75. STRING* p = GET_STRING(cell);
  76. size_t len = p->len;
  77. char* data = p->data;
  78. if (strict) {
  79. // FIXME -- make this more efficient, and escape other special chars?
  80. fputc('"', fp);
  81. while(len--) {
  82. char ch = *data++;
  83. if (ch == '"' || ch == '\\') {
  84. fputc('\\', fp);
  85. }
  86. fputc(ch, fp);
  87. }
  88. fputc('"', fp);
  89. }
  90. else {
  91. fwrite(data, 1, len, fp);
  92. }
  93. }
  94. break;
  95. case T_NAME:
  96. {
  97. NAME* p = GET_NAME(cell);
  98. if (p->gensym) {
  99. fprintf(fp, "#_%d", p->gensym);
  100. }
  101. else {
  102. fwrite(GET_NAME(cell)->data, 1, GET_NAME(cell)->len, fp);
  103. }
  104. }
  105. break;
  106. case T_KEYWORD:
  107. {
  108. KEYWORD* p = GET_KEYWORD(cell);
  109. fwrite(p->data, 1, p->len, fp);
  110. fputc(':', fp);
  111. }
  112. break;
  113. case T_SLOT:
  114. fprintf(fp, "#<slot:%d>", GET_SLOT(cell));
  115. break;
  116. // FIXME - arbitrary recursion
  117. case T_CONS:
  118. fputc('(', fp);
  119. if (tab) ++tab;
  120. int did = 0;
  121. while(1) {
  122. int pair = CONSP(CAR(cell));
  123. if (!did && tab && pair && !CONSP(CAR(CAR(cell)))) { fprintf(fp, "\n%*s", (tab-1)*2, ""); }
  124. internal_generic_output(fp, CAR(cell), strict, tab);
  125. cell = CDR(cell);
  126. if (NULLP(cell)) {
  127. break;
  128. }
  129. did = (tab && pair);
  130. if (did) { fprintf(fp, "\n%*s", (tab-1)*2, ""); }
  131. else fputc(' ', fp);
  132. if (!CONSP(cell)) {
  133. fputs(". ", fp);
  134. internal_generic_output(fp, cell, strict, tab);
  135. break;
  136. }
  137. }
  138. fputc(')', fp);
  139. break;
  140. // FIXME - arbitrary recursion
  141. case T_VECTOR:
  142. {
  143. VECTOR *vec = GET_VECTOR(cell);
  144. fputs("#(", fp);
  145. if (vec->len > 0) {
  146. int i = 0;
  147. internal_generic_output(fp, vec->data[i++], strict, tab);
  148. while(i < vec->len) {
  149. fputc(' ', fp);
  150. internal_generic_output(fp, vec->data[i++], strict, tab);
  151. }
  152. }
  153. fputc(')', fp);
  154. break;
  155. }
  156. case T_FUNC:
  157. fprintf(fp, "#<primitive:%s>", GET_FUNC(cell)->name);
  158. break;
  159. case T_COMPILED_LAMBDA:
  160. fprintf(fp, "#<compiled-lambda:0x%08x>", AS_LITERAL(cell));
  161. break;
  162. {
  163. if (tab) ++tab;
  164. COMPILED_LAMBDA *l = GET_COMPILED_LAMBDA(cell);
  165. fprintf(fp, "#<%s %d%s:%d/%d",
  166. l->is_macro ? "macro" : "lambda",
  167. l->argc, l->rest ? "+" : "",
  168. l->depth,
  169. l->max_slot);
  170. if (tab) { fprintf(fp, "\n%*s", (tab-1)*2, ""); }
  171. else { fputc(' ', fp); }
  172. internal_generic_output(fp, l->body, strict, tab);
  173. fputc('>', fp);
  174. }
  175. break;
  176. case T_CLOSURE:
  177. fprintf(fp, "#<closure:0x%08x>", AS_LITERAL(cell));
  178. break;
  179. {
  180. if (tab) ++tab;
  181. CLOSURE *c = GET_CLOSURE(cell);
  182. fprintf(fp, "#<closure ");
  183. if (tab) { fprintf(fp, "\n%*s", (tab-1)*2, ""); }
  184. internal_print_env(fp, c->env);
  185. if (tab) { fprintf(fp, "\n%*s", (tab-1)*2, ""); }
  186. fputc(' ', fp);
  187. internal_generic_output(fp, c->compiled_lambda, strict, tab);
  188. fputc('>', fp);
  189. }
  190. break;
  191. case T_EXCEPTION:
  192. fputs("#<exception:", fp);
  193. fwrite(GET_EXCEPTION(cell)->data, 1, GET_EXCEPTION(cell)->len, fp);
  194. fputc('>', fp);
  195. break;
  196. case T_REIFIED_CONTINUATION:
  197. fprintf(fp, "#<continuation:0x%08x>", (int)GET_REIFIED_CONTINUATION(cell)->cont);
  198. break;
  199. case T_STACK_FRAME:
  200. {
  201. STACK_FRAME* p = GET_STACK_FRAME(cell);
  202. fputs("#<stack-frame [", fp);
  203. int i;
  204. for(i = 0; i < p->len; ++i) {
  205. if (i) fputc(' ', fp);
  206. fprintf(fp, "0x%08x", (int)p->cells[i]);
  207. }
  208. fputs("]>", fp);
  209. }
  210. break;
  211. case T_ENV:
  212. fprintf(fp, "#<env:count=%d>", GET_ENV(cell)->count);
  213. break;
  214. case T_RELOC:
  215. fprintf(fp, "#<reloc:0x%08x>", (int)GET_RELOC(cell));
  216. break;
  217. case T_PORT:
  218. fprintf(fp, "#<port:%s>", GET_PORT(cell)->data);
  219. break;
  220. case T_DB_CONNECTION:
  221. fprintf(fp, "#<db-connection>");
  222. break;
  223. case T_DB_RESULT:
  224. fprintf(fp, "#<db-result>");
  225. break;
  226. case T_RECORD:
  227. fprintf(fp, "#<record>");
  228. break;
  229. default:
  230. fprintf(fp, "#<%s-%02x:%08x>",
  231. IS_LITERAL(cell) ? "literal" : "pointer",
  232. GET_TYPE(cell),
  233. AS_LITERAL(cell)
  234. );
  235. break;
  236. }
  237. }
  238. void internal_print(FILE* fp, CELL cell)
  239. {
  240. internal_generic_output(fp, cell, 1, 0);
  241. }
  242. void print_register_symbols()
  243. {
  244. }