1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-20 18:18:51 +03:00
mal/c/printer.c
Joel Martin b8ee29b22f All: add keywords.
Also, fix nth and count to match cloure.
2015-01-09 16:16:50 -06:00

152 lines
4.7 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,
*key2 = 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);
if (((char*)key)[0] == '\x7f') {
key2 = g_strdup_printf("%s", (char*)key);
key2[0] = ':';
} else {
key2 = g_strdup_printf("\"%s\"", (char*)key);
}
repr_tmp1 = _pr_str((MalVal*)value, print_readably);
if (start) {
start = 0;
repr = g_strdup_printf("{%s %s", (char*)key2, repr_tmp1);
} else {
repr_tmp2 = repr;
repr = g_strdup_printf("%s %s %s", repr_tmp2, (char*)key2, 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 (obj->val.string[0] == '\x7f') {
// Keyword
repr = g_strdup_printf("%s", obj->val.string);
repr[0] = ':';
} else 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("%s", ""),
*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;
}