-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathsnek-print.c
156 lines (149 loc) · 3.44 KB
/
snek-print.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
* Copyright © 2019 Keith Packard <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include "snek.h"
static inline char snek_list_open(snek_list_type_t type)
{
switch(type) {
case snek_list_list:
return '[';
default:
#ifndef SNEK_NO_DICT
return '{';
case snek_list_tuple:
#endif
return '(';
}
}
static inline char snek_list_close(snek_list_type_t type)
{
switch(type) {
case snek_list_list:
return ']';
default:
#ifndef SNEK_NO_DICT
return '}';
case snek_list_tuple:
#endif
return ')';
}
}
#ifndef printf_float
#define printf_float(x) ((double) (x))
#endif
void
snek_poly_format(snek_buf_t *buf, snek_poly_t a, char format)
{
void *closure = buf->closure;
static char tmp[32];
char format_string[3];
snek_type_t atype = snek_poly_type(a);
int i;
format_string[0] = '%';
format_string[1] = format;
format_string[2] = '\0';
switch (format) {
case 'd':
case 'i':
case 'o':
case 'x':
case 'X':
if (atype != snek_float)
break;
print_float:
i = (int) snek_poly_to_float(a);
print_int:
sprintf(tmp, format_string, i);
buf->put_s(tmp, closure);
return;
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G':
if (atype != snek_float)
break;
strfromf(tmp, sizeof(tmp), format_string, snek_poly_to_float(a));
buf->put_s(tmp, closure);
return;
case 'c':
switch (atype) {
case snek_float:
goto print_float;
case snek_string:
i = snek_poly_to_string(a)[0];
goto print_int;
default:
break;
}
break;
case 's':
if (atype == snek_string) {
buf->put_s(snek_poly_to_string(a), closure);
return;
}
format='a';
break;
default:
break;
}
if (snek_is_null(a))
buf->put_s("None", closure);
else switch (atype) {
case snek_float:
strfromf_const(tmp, sizeof(tmp), "%.9g", snek_poly_to_float(a));
buf->put_s(tmp, closure);
break;
case snek_string:
buf->put_c('\'', closure);
buf->put_s(snek_poly_to_string(a), closure);
buf->put_c('\'', closure);
break;
case snek_func:
sprintf_const(tmp, "<function at %d>",
snek_poly_to_offset(a));
buf->put_s(tmp, closure);
break;
case snek_builtin:
sprintf_const(tmp, "<builtin %s>",
snek_name_string(snek_poly_to_builtin_id(a)));
buf->put_s(tmp, closure);
break;
case snek_list:
{
snek_list_t *list = snek_poly_to_list(a);
snek_list_type_t type = snek_list_type(list);
snek_offset_t size = list->size;
snek_stack_push_list(list);
buf->put_c(snek_list_open(type), closure);
for (snek_offset_t o = 0; o < size; o++) {
list = snek_stack_pop_list();
snek_stack_push_list(list);
snek_poly_format(buf, snek_list_data(list)[o], format);
#ifdef SNEK_NO_DICT
#define list_sep_char(type,o) ','
#else
#define list_sep_char(type,o) (((type) == snek_list_dict && !((o)&1)) ? ':' : ',')
#endif
if (o < size - 1 || (size == 1 && type == snek_list_tuple)) {
buf->put_c(list_sep_char(type, o), closure);
buf->put_c(' ', closure);
}
}
list = snek_stack_pop_list();
buf->put_c(snek_list_close(type), closure);
break;
}
}
}