1
1
mirror of https://github.com/kanaka/mal.git synced 2024-11-10 12:47:45 +03:00
mal/c/printer.c
Joel Martin ea81a8087b All: split types into types, env, printer, core.
- types: low-level mapping to the implementation language.
- core: functions on types that are exposed directly to mal.
- printer: implementation called by pr-str, str, prn, println.
- env: the environment implementation

- Also, unindent all TCO while loops so that the diff of step4 and
  step5 are minimized.
2014-04-02 22:23:37 -05:00

141 lines
4.3 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include "types.h"
#include "printer.h"
char *_pr_str_hash_map(MalVal *obj, int print_readably) {
int start = 1;
char *repr = NULL, *repr_tmp1 = NULL, *repr_tmp2 = NULL;
GHashTableIter iter;
gpointer key, value;
repr = g_strdup_printf("{");
g_hash_table_iter_init (&iter, obj->val.hash_table);
while (g_hash_table_iter_next (&iter, &key, &value)) {
//g_print ("%s/%p ", (const char *) key, (void *) value);
repr_tmp1 = _pr_str((MalVal*)value, print_readably);
if (start) {
start = 0;
repr = g_strdup_printf("{\"%s\" %s", (char *)key, repr_tmp1);
} else {
repr_tmp2 = repr;
repr = g_strdup_printf("%s \"%s\" %s", repr_tmp2, (char *)key, repr_tmp1);
free(repr_tmp2);
}
free(repr_tmp1);
}
repr_tmp2 = repr;
repr = g_strdup_printf("%s}", repr_tmp2);
free(repr_tmp2);
return repr;
}
char *_pr_str_list(MalVal *obj, int print_readably, char start, char end) {
int i;
char *repr = NULL, *repr_tmp1 = NULL, *repr_tmp2 = NULL;
repr = g_strdup_printf("%c", start);
for (i=0; i<_count(obj); i++) {
repr_tmp1 = _pr_str(g_array_index(obj->val.array, MalVal*, i),
print_readably);
if (i == 0) {
repr = g_strdup_printf("%c%s", start, repr_tmp1);
} else {
repr_tmp2 = repr;
repr = g_strdup_printf("%s %s", repr_tmp2, repr_tmp1);
free(repr_tmp2);
}
free(repr_tmp1);
}
repr_tmp2 = repr;
repr = g_strdup_printf("%s%c", repr_tmp2, end);
free(repr_tmp2);
return repr;
}
// Return a string representation of the MalVal object. Returned string must
// be freed by caller.
char *_pr_str(MalVal *obj, int print_readably) {
char *repr = NULL;
if (obj == NULL) { return NULL; }
switch (obj->type) {
case MAL_NIL:
repr = g_strdup_printf("nil");
break;
case MAL_TRUE:
repr = g_strdup_printf("true");
break;
case MAL_FALSE:
repr = g_strdup_printf("false");
break;
case MAL_STRING:
if (print_readably) {
char *repr_tmp = g_strescape(obj->val.string, "");
repr = g_strdup_printf("\"%s\"", repr_tmp);
free(repr_tmp);
} else {
repr = g_strdup_printf("%s", obj->val.string);
}
break;
case MAL_SYMBOL:
repr = g_strdup_printf("%s", obj->val.string);
break;
case MAL_INTEGER:
repr = g_strdup_printf("%" G_GINT64_FORMAT, obj->val.intnum);
break;
case MAL_FLOAT:
repr = g_strdup_printf("%f", obj->val.floatnum);
break;
case MAL_HASH_MAP:
repr = _pr_str_hash_map(obj, print_readably);
break;
case MAL_LIST:
repr = _pr_str_list(obj, print_readably, '(', ')');
break;
case MAL_VECTOR:
repr = _pr_str_list(obj, print_readably, '[', ']');
break;
case MAL_ATOM:
repr = g_strdup_printf("(atom %s)",
_pr_str(obj->val.atom_val, print_readably));
break;
case MAL_FUNCTION_C:
repr = g_strdup_printf("#<function@%p>", obj->val.f0);
break;
case MAL_FUNCTION_MAL:
repr = g_strdup_printf("#<Function: (fn* %s %s)>",
_pr_str(obj->val.func.args, print_readably),
_pr_str(obj->val.func.body, print_readably));
break;
default:
printf("pr_str unknown type %d\n", obj->type);
repr = g_strdup_printf("<unknown>");
}
return repr;
}
// Return a string representation of the MalVal arguments. Returned string must
// be freed by caller.
char *_pr_str_args(MalVal *args, char *sep, int print_readably) {
assert_type(args, MAL_LIST|MAL_VECTOR,
"_pr_str called with non-sequential args");
int i;
char *repr = g_strdup_printf(""),
*repr2 = NULL;
for (i=0; i<_count(args); i++) {
MalVal *obj = g_array_index(args->val.array, MalVal*, i);
if (i != 0) {
repr2 = repr;
repr = g_strdup_printf("%s%s", repr2, sep);
free(repr2);
}
repr2 = repr;
repr = g_strdup_printf("%s%s",
repr2, _pr_str(obj, print_readably));
free(repr2);
}
return repr;
}