Browse Source

working on type inference

Tobias Waldekranz.com 8 years ago
parent
commit
e27f028200
7 changed files with 241 additions and 193 deletions
  1. 17 0
      func.h
  2. 139 131
      global.c
  3. 11 1
      node.c
  4. 11 0
      node.h
  5. 43 50
      ply.c
  6. 1 1
      sym.c
  7. 19 10
      type.c

+ 17 - 0
func.h

@@ -0,0 +1,17 @@
1
+#ifndef _FUNC_H
2
+#define _FUNC_H
3
+
4
+struct node;
5
+struct prog;
6
+struct type;
7
+
8
+struct func {
9
+	const char *name;
10
+	struct type *type;
11
+
12
+	int (*static_verify)(struct node *);
13
+	
14
+	int (*type_infer)(struct prog *, struct node *);
15
+};
16
+
17
+#endif	/* _FUNC_H */

+ 139 - 131
global.c

@@ -1,164 +1,132 @@
1
+#include <assert.h>
1 2
 #include <errno.h>
2 3
 #include <string.h>
3 4
 
5
+#include "arch.h"
4 6
 #include "func.h"
5 7
 #include "node.h"
6 8
 #include "ply.h"
7 9
 #include "sym.h"
10
+#include "type.h"
8 11
 
9
-#if 0
10
-/* pid */
11 12
 
12
-int pid_generate_ir(prog_t *prog, node_t *node)
13
+static struct type *global_map_ktype(struct node *n)
13 14
 {
14
-	/* TODO */
15
-	return 0;
16
-}
15
+	struct node *map, *key;
16
+	struct type *ktype;
17
+	int nargs = node_nargs(n);
17 18
 
18
-type_t t_pid_t = {
19
-	.ttype = T_TYPEDEF,
19
+	map = n->expr.args;
20 20
 
21
-	.t.tdef = {
22
-		.name = "__ply_pid_t",
23
-		.type = &t_u32,
24
-	},
25
-};
21
+	if (node_nargs(n) == 2)
22
+		return map->next->sym->type;
26 23
 
27
-type_t t_pid_func = {
28
-	.ttype = T_FUNC,
29
-
30
-	.t.func = {
31
-		.name = "pid",
32
-		.type = &t_pid_t,
33
-		.args = NULL,
34
-		.generate_ir = pid_generate_ir,
35
-	},
36
-};
24
+	assert(0);
25
+	return NULL;
26
+}
37 27
 
38
-type_t *ts_pid[] = { &t_pid_t, &t_pid_func, NULL };
28
+static int global_assign_type_infer_map(struct node *n)
29
+{
30
+	struct node *map, *key;
31
+	struct type *ktype;
39 32
 
33
+	map = n->expr.args;
40 34
 
41
-/* quantize */
35
+	for (key = map->next; key; key = key->next) {
36
+		node_print(key, stdout);printf("WKZ\n");
37
+		if (type_sizeof(key->sym->type) < 0)
38
+			return 0;
39
+		node_print(key, stdout);printf("WKZ\n");
40
+	}
42 41
 
43
-int quantize_generate_ir(prog_t *prog, node_t *node)
44
-{
45
-	/* TODO */
42
+	map->sym->type = type_map_of(global_map_ktype(n), n->sym->type);
46 43
 	return 0;
47 44
 }
48 45
 
49
-type_t t_u64_64 = {
50
-	.ttype = T_ARRAY,
51
-	.t.array = {
52
-		.type = &t_u64,
53
-		.len = 64,
54
-	},
55
-};
46
+static int global_assign_type_infer(struct prog *prog, struct node *n)
47
+{
48
+	struct node *lval, *rval;
56 49
 
57
-type_t t_quantize_t = {
58
-	.ttype = T_TYPEDEF,
50
+	lval = n->expr.args;
51
+	rval = lval->next;
59 52
 
60
-	.t.tdef = {
61
-		.name = "__ply_quantize_t",
62
-		.type = &t_u64_64,
63
-	},
64
-};
53
+	if (!rval->sym->type)
54
+		return 0;
65 55
 
66
-field_t f_quantize_args[] = {
67
-	{ .type = &t_s64 },
68
-	{ .type = NULL }
69
-};
56
+	if (!lval->sym->type) {
57
+		lval->sym->type = rval->sym->type;
70 58
 
71
-type_t t_quantize_func = {
72
-	.ttype = T_FUNC,
59
+		if (node_is_map(lval))
60
+			return global_assign_type_infer_map(lval);
73 61
 
74
-	.t.func = {
75
-		.name = "quantize",
76
-		.type = &t_quantize_t,
77
-		.args = f_quantize_args,
78
-		.generate_ir = quantize_generate_ir,
79
-	},
80
-};
62
+		return 0;
63
+	}
81 64
 
82
-type_t *ts_quantize[] = { &t_u64_64, &t_quantize_t, &t_quantize_func, NULL };
65
+	if (type_compatible(lval->sym->type, rval->sym->type))
66
+		return 0;
83 67
 
68
+	if (lval->ntype == N_IDENT) {
69
+		node_error(n, stderr, "conflicting types for '%s'",
70
+			   lval->ident.name);
71
+	} else {
72
+		node_error(n, stderr, "conflicting types for '%s'",
73
+			   lval->expr.args->ident.name);
74
+	}
84 75
 
85
-/* time */
76
+	return -EINVAL;
77
+}
86 78
 
87
-int time_generate_ir(prog_t *prog, node_t *node)
79
+static int global_assign_static_verify(struct node *n)
88 80
 {
89
-	ir_emit_call(prog->ir, BPF_FUNC_ktime_get_ns);
81
+	struct node *lval;
82
+	int nargs = node_nargs(n);
90 83
 
91
-	irs_alloc_reg(&node->irs, prog->ir);
92
-	ir_emit_insn(prog->ir, MOV(0, 0), node->irs.reg, BPF_REG_0);
93
-	return 0;
84
+	if (nargs != 2) {
85
+		node_error(n, stderr, "assignment operator expects 2 arguments,"
86
+			   " %d given", nargs);
87
+		return -EINVAL;
88
+	}
89
+
90
+	lval = n->expr.args;
91
+
92
+	if (node_is_map(lval) || (lval->ntype == N_IDENT))
93
+		return 0;
94
+
95
+	node_error(n, stderr, "assignment destination must be a variable or map");
96
+	return -EINVAL;
94 97
 }
95 98
 
96
-type_t t_time_t = {
99
+struct type t_pid = {
97 100
 	.ttype = T_TYPEDEF,
98 101
 
99
-	.t.tdef = {
100
-		.name = "__ply_time_t",
101
-		.type = &t_s64,
102
-	},
102
+	.tdef = { .name = ":pid", .type = &t_u32 },
103 103
 };
104 104
 
105
-type_t t_time_func = {
106
-	.ttype = T_FUNC,
105
+struct type t_time = {
106
+	.ttype = T_TYPEDEF,
107 107
 
108
-	.t.func = {
109
-		.name = "time",
110
-		.type = &t_time_t,
111
-		.args = NULL,
112
-		.generate_ir = time_generate_ir,
113
-	},
108
+	.tdef = { .name = ":time", .type = &t_s64 },
114 109
 };
115 110
 
116
-type_t *ts_time[] = { &t_time_t, &t_time_func, NULL };
117
-
118
-#endif
119
-
120
-/* int global_resolve(prog_t *prog, node_t *n) */
121
-/* { */
122
-/* 	type_t **ts = NULL; */
123
-/* 	type_t *t; */
124
-/* 	int err; */
125
-
126
-/* 	if (!strcmp(n->ident, "pid")) { */
127
-/* 		ts = ts_pid; */
128
-/* 		t = &t_pid_func; */
129
-/* 	} else if (!strcmp(n->ident, "quantize")) { */
130
-/* 		ts = ts_quantize; */
131
-/* 		t = &t_quantize_func; */
132
-/* 	} else if (!strcmp(n->ident, "time")) { */
133
-/* 		ts = ts_time; */
134
-/* 		t = &t_time_func; */
135
-/* 	} else { */
136
-/* 		return -ENOENT; */
137
-/* 	} */
138
-
139
-/* 	if (ts) { */
140
-/* 		err = type_add_list(ts); */
141
-/* 		if (err) */
142
-/* 			return err; */
143
-/* 	} */
144
-
145
-/* 	n->type = t; */
146
-/* 	return sym_add(prog->locals, n->ident, t, &n->sym); */
147
-/* } */
148
-
149 111
 static const struct func global_funcs[] = {
150
-
151
-	/* block */
152
-	{ .name = "{}", },
112
+	{ .name = ":block", .type = &t_void, },
153 113
 
154 114
 	{ .name = "+", },
155 115
 	{ .name = "-", },
156 116
 	
157
-	{ .name = "=", },
158
-	{ .name = "[]", },
117
+	{
118
+		.name = ":assign",
119
+		.static_verify = global_assign_static_verify,
120
+		.type_infer = global_assign_type_infer,
121
+	},
122
+	{
123
+		.name = ":map",
124
+		/* .static_verify = global_map_static_verify, */
125
+		/* .type_infer = global_map_type_infer, */
126
+	},
159 127
 
160
-	{ .name = "pid", },
161
-	{ .name = "time", },
128
+	{ .name = "pid",  .type = &t_pid, },
129
+	{ .name = "time", .type = &t_time, },
162 130
 
163 131
 	{ .name = "quantize", },
164 132
 	
@@ -167,43 +135,83 @@ static const struct func global_funcs[] = {
167 135
 
168 136
 static const struct func global_num_func = {
169 137
 	.name = ":num",
138
+	.type = &t_int,
139
+};
140
+
141
+struct type t_string_array = {
142
+	.ttype = T_ARRAY,
143
+
144
+	.array = { .type = &t_char, .len = 64 }, /* TODO: tunable */
145
+};
146
+
147
+struct type t_string = {
148
+	.ttype = T_TYPEDEF,
149
+
150
+	.tdef = { .name = ":string", .type = &t_string_array },
170 151
 };
171 152
 
172 153
 static const struct func global_string_func = {
173 154
 	.name = ":string",
155
+	.type = &t_string,
174 156
 };
175 157
 
176 158
 static const struct func global_ident_func = {
177 159
 	.name = ":ident",
178 160
 };
179 161
 
162
+static const struct func *global_sym_alloc_expr(struct node *n)
163
+{
164
+	const struct func *func;
165
+	int err;
166
+
167
+	for (func = global_funcs; func->name; func++) {
168
+		if (strcmp(func->name, n->expr.func))
169
+			continue;
170
+
171
+		return func;
172
+	}
173
+
174
+	return NULL;
175
+}
176
+
180 177
 int global_sym_alloc(struct prog *prog, struct node *n)
181 178
 {
182 179
 	const struct func *func;
180
+	struct symtab *st = prog->locals;
181
+	int err;
183 182
 
184 183
 	switch (n->ntype) {
185 184
 	case N_EXPR:
186
-		for (func = global_funcs; func->name; func++) {
187
-			if (strcmp(func->name, n->expr.func))
188
-				continue;
189
-
190
-			n->sym = sym_alloc(prog->locals, n, func);
191
-			return 0;
192
-		}
193
-
194
-		return -ENOENT;
185
+		func = global_sym_alloc_expr(n);
186
+		break;
195 187
 	case N_IDENT:
196
-		n->sym = sym_alloc(prog->globals, n, &global_ident_func);
197
-		return 0;
188
+		st = prog->globals;
189
+		func = &global_ident_func;
190
+		break;
198 191
 	case N_NUM:
199
-		n->sym = sym_alloc(prog->locals, n, &global_num_func);
200
-		return 0;
192
+		func = &global_num_func;
193
+		break;
201 194
 	case N_STRING:
202
-		n->sym = sym_alloc(prog->locals, n, &global_string_func);
203
-		return 0;
195
+		func = &global_string_func;
196
+		break;
204 197
 	}
205 198
 
206
-	return -ENOENT;
199
+	if (!func)
200
+		return -ENOENT;
201
+
202
+	if (func->static_verify) {
203
+		err = func->static_verify(n);
204
+		if (err)
205
+			return err;
206
+	}
207
+
208
+	n->sym = sym_alloc(st, n, func);
209
+
210
+	if (func->type)
211
+		/* return type is static, fill it now */
212
+		n->sym->type = func->type;
213
+
214
+	return 0;
207 215
 }
208 216
 
209 217
 int global_probe(struct prog *prog)

+ 11 - 1
node.c

@@ -96,6 +96,8 @@ void node_error(struct node *n, FILE *fp, const char *fmt, ...)
96 96
 	va_start(ap, fmt);
97 97
 	vfprintf(fp, fmt, ap);
98 98
 	va_end(ap);
99
+
100
+	fputc('\n', fp);
99 101
 }
100 102
 
101 103
 int node_walk(struct node *n,
@@ -149,7 +151,15 @@ int node_is_block(struct node *n)
149 151
 	if (!n || (n->ntype != N_EXPR))
150 152
 		return 0;
151 153
 
152
-	return !strcmp(n->expr.func, "{}");
154
+	return !strcmp(n->expr.func, ":block");
155
+}
156
+
157
+int node_is_map(struct node *n)
158
+{
159
+	if (!n || (n->ntype != N_EXPR))
160
+		return 0;
161
+
162
+	return !strcmp(n->expr.func, ":map");
153 163
 }
154 164
 
155 165
 

+ 11 - 0
node.h

@@ -60,7 +60,18 @@ struct node *node_expr  (char *func, ...);
60 60
 
61 61
 /* helpers */
62 62
 
63
+static inline int node_nargs(struct node *n)
64
+{
65
+	struct node *arg;
66
+	int nargs = 0;
67
+
68
+	for (arg = n->expr.args; arg; arg = arg->next, nargs++);
69
+
70
+	return nargs;
71
+}
72
+
63 73
 int node_is_block(struct node *n);
74
+int node_is_map  (struct node *n);
64 75
 
65 76
 #define node_expr_foreach(_expr, _arg) \
66 77
 	for ((_arg) = (_expr)->expr.args; (_arg); (_arg) = (_arg)->next)

+ 43 - 50
ply.c

@@ -4,6 +4,7 @@
4 4
 #include <stdlib.h>
5 5
 #include <string.h>
6 6
 
7
+#include "func.h"
7 8
 #include "node.h"
8 9
 #include "ply.h"
9 10
 #include "sym.h"
@@ -68,22 +69,27 @@ struct ctx *ctx_get(void)
68 69
 	prog->probe = "k:SyS_read";
69 70
 
70 71
 	/* { 
72
+	 * 	us = pid();
71 73
 	 * 	@t[0] = time();
72
-	 * 	@reads[pid()] = quantize(arg2)
74
+	 * 	@reads[pid()] = quantize(arg2);
73 75
 	 * }
74 76
 	 */
75 77
 	prog->ast =
76
-		node_expr("{}",
77
-			  node_expr("=",
78
-				    node_expr("[]",
79
-					      node_ident("@t"),
78
+		node_expr(":block",
79
+			  node_expr(":assign",
80
+				    node_ident("us"),
81
+				    node_expr("pid", NULL),
82
+				    NULL),
83
+			  node_expr(":assign",
84
+				    node_expr(":map",
85
+					      node_ident("t"),
80 86
 					      node_num(0),
81 87
 					      NULL),
82 88
 				    node_expr("time", NULL),
83 89
 				    NULL),
84
-			  node_expr("=",
85
-				    node_expr("[]",
86
-					      node_ident("@reads"),
90
+			  node_expr(":assign",
91
+				    node_expr(":map",
92
+					      node_ident("reads"),
87 93
 					      node_expr("pid", NULL),
88 94
 					      NULL),
89 95
 				    node_expr("quantize", node_ident("arg2"), NULL),
@@ -104,9 +110,9 @@ struct ctx *ctx_get(void)
104 110
 	prog->probe = "k:SyS_read2"; 
105 111
 	/* { @times[pid()] = quantize(time() - t0) } */
106 112
 	prog->ast =
107
-		node_expr("=",
108
-			  node_expr("[]",
109
-				    node_ident("@times"),
113
+		node_expr(":assign",
114
+			  node_expr(":map",
115
+				    node_ident("times"),
110 116
 				    node_expr("pid", NULL),
111 117
 				    NULL),
112 118
 			  node_expr("quantize",
@@ -147,17 +153,15 @@ int pass_sym_alloc(struct node *n, void *_prog)
147 153
 	}
148 154
 
149 155
 	if (err) {
150
-		if (n->ntype == N_EXPR)
156
+		if ((err == -ENOENT) && (n->ntype == N_EXPR))
151 157
 			node_error(n, stderr, "unknown function '%s'",
152 158
 				   n->expr.func);
153
-		else
154
-			assert(0);
155 159
 	}
156 160
 
157 161
 	return err;
158 162
 }
159 163
 
160
-/* int infer_type_list(struct prog *prog, node_t *n) */
164
+/* int infer_type_list(struct prog *prog, struct node *n) */
161 165
 /* { */
162 166
 /* 	type_t *t; */
163 167
 
@@ -181,9 +185,9 @@ int pass_sym_alloc(struct node *n, void *_prog)
181 185
 /* 	return 0; */
182 186
 /* } */
183 187
 
184
-/* int infer_type_keyword(struct prog *prog, node_t *n) */
188
+/* int infer_type_keyword(struct prog *prog, struct node *n) */
185 189
 /* { */
186
-/* 	node_t *dst, *src; */
190
+/* 	struct node *dst, *src; */
187 191
 
188 192
 /* 	switch (n->keyword.class) { */
189 193
 /* 	case KW_ASSIGN: */
@@ -227,9 +231,9 @@ int pass_sym_alloc(struct node *n, void *_prog)
227 231
 /* 	return -ENOSYS; */
228 232
 /* } */
229 233
 
230
-/* int infer_type_sym(struct prog *prog, node_t *n) */
234
+/* int infer_type_sym(struct prog *prog, struct node *n) */
231 235
 /* { */
232
-/* 	node_t *parent, *key; */
236
+/* 	struct node *parent, *key; */
233 237
 
234 238
 /* 	if (n->sym->type) { */
235 239
 /* 		/\* the symbol type could have been inferred in another */
@@ -258,30 +262,19 @@ int pass_sym_alloc(struct node *n, void *_prog)
258 262
 /* 	return 0; */
259 263
 /* } */
260 264
 
261
-/* int pass_infer_types(node_t *n, void *_prog) */
262
-/* { */
263
-/* 	struct prog *prog = _prog; */
265
+int pass_type_infer(struct node *n, void *_prog)
266
+{
267
+	struct prog *prog = _prog;
264 268
 
265
-/* 	if (n->type) */
266
-/* 		return 0; */
269
+	if (n->sym->func->type_infer)
270
+		return n->sym->func->type_infer(prog, n);
267 271
 
268
-/* 	switch (n->ntype) { */
269
-/* 	case N_LIST: */
270
-/* 		return infer_type_list(prog, n); */
271
-/* 	case N_KEYWORD: */
272
-/* 		return infer_type_keyword(prog, n); */
273
-/* 	case N_IDENT: */
274
-/* 		return infer_type_sym(prog, n); */
275
-/* 	default: */
276
-/* 		break; */
277
-/* 	} */
278
-
279
-/* 	return 0; */
280
-/* } */
272
+	return 0;
273
+}
281 274
 
282
-/* int validate_func(node_t *n) */
275
+/* int validate_func(struct node *n) */
283 276
 /* { */
284
-/* 	node_t *arg; */
277
+/* 	struct node *arg; */
285 278
 /* 	field_t *f; */
286 279
 /* 	int i; */
287 280
 
@@ -316,7 +309,7 @@ int pass_sym_alloc(struct node *n, void *_prog)
316 309
 /* 	return -EINVAL;	 */
317 310
 /* } */
318 311
 
319
-/* int pass_validate_types(node_t *n, void *_prog) */
312
+/* int pass_validate_types(struct node *n, void *_prog) */
320 313
 /* { */
321 314
 /* 	struct prog *prog = _prog; */
322 315
 
@@ -363,10 +356,10 @@ int pass_sym_alloc(struct node *n, void *_prog)
363 356
 
364 357
 /* } */
365 358
 
366
-/* int rewrite_const_math(node_t *n) */
359
+/* int rewrite_const_math(struct node *n) */
367 360
 /* { */
368 361
 /* 	int64_t result; */
369
-/* 	node_t *a, *b, *new; */
362
+/* 	struct node *a, *b, *new; */
370 363
 /* 	int op; */
371 364
 
372 365
 /* 	/\* TODO: handle L/UL/ULL correctly *\/ */
@@ -391,7 +384,7 @@ int pass_sym_alloc(struct node *n, void *_prog)
391 384
 /* 	return node_replace(n, new); */
392 385
 /* } */
393 386
 
394
-/* int pass_rewrite_ast(node_t *n, void *_prog) */
387
+/* int pass_rewrite_ast(struct node *n, void *_prog) */
395 388
 /* { */
396 389
 /* 	struct prog *prog = _prog; */
397 390
 /* 	provider_t *global = provider_get(":"); */
@@ -420,7 +413,7 @@ int pass_sym_alloc(struct node *n, void *_prog)
420 413
 /* 	return 0; */
421 414
 /* } */
422 415
 
423
-/* int generate_ir_ident(struct prog *prog, node_t *n) */
416
+/* int generate_ir_ident(struct prog *prog, struct node *n) */
424 417
 /* { */
425 418
 
426 419
 /* 	switch (n->sym->type->ttype) { */
@@ -436,7 +429,7 @@ int pass_sym_alloc(struct node *n, void *_prog)
436 429
 /* 	return 0; */
437 430
 /* } */
438 431
 
439
-/* int pass_generate_ir(node_t *n, void *_prog) */
432
+/* int pass_generate_ir(struct node *n, void *_prog) */
440 433
 /* { */
441 434
 /* 	struct prog *prog = _prog; */
442 435
 
@@ -499,7 +492,7 @@ int run_walk(struct pass *pass, struct ctx *ctx)
499 492
 
500 493
 struct pass passes[] = {
501 494
 	{ .run = run_walk, .post = pass_sym_alloc },
502
-	/* { .run = run_walk, .post = pass_infer_types }, */
495
+	{ .run = run_walk, .post = pass_type_infer },
503 496
 	/* { .run = run_walk, .post = pass_infer_types }, */
504 497
 	/* { .run = run_walk, .post = pass_infer_types }, */
505 498
 	/* { .run = run_validate_types, .post = pass_validate_types }, */
@@ -525,14 +518,14 @@ int main(void)
525 518
 	for (prog = ctx->progs; *prog; prog++) {
526 519
 		printf("\n\e[34m%s\e[0m\n", (*prog)->probe);
527 520
 		node_dump((*prog)->ast, stdout);
528
-		/* printf("\n-- locals\n"); */
529
-		/* symtab_dump((*prog)->locals, stdout); */
521
+		printf("\n-- locals\n");
522
+		symtab_dump((*prog)->locals, stdout);
530 523
 		/* printf("-- ir\n"); */
531 524
 		/* ir_dump((*prog)->ir, stdout); */
532 525
 	}
533 526
 
534
-	/* printf("\n\n-- globals\n"); */
535
-	/* symtab_dump(ctx->globals, stdout); */
527
+	printf("\n\n-- globals\n");
528
+	symtab_dump(ctx->globals, stdout);
536 529
 
537 530
 	if (err)
538 531
 		printf("ERR: %d\n", err);

+ 1 - 1
sym.c

@@ -21,7 +21,7 @@ static struct sym *__sym_alloc(struct symtab *st, const char *name,
21 21
 	sym->st   = st;
22 22
 	sym->name = name;
23 23
 	sym->func = func;
24
-	return 0;
24
+	return sym;
25 25
 }
26 26
 
27 27
 static struct sym *sym_alloc_ident(struct symtab *st, struct node *n,

+ 19 - 10
type.c

@@ -30,20 +30,20 @@ static void type_dump_func(struct type *t, const char *name, FILE *fp)
30 30
 
31 31
 void type_dump(struct type *t, const char *name, FILE *fp)
32 32
 {
33
-	if (!t) {
34
-		fputs("<NONE>", fp);
35
-		return;
36
-	}
33
+	if (!t)
34
+		goto print_void;
35
+
37 36
 
38 37
 	switch (t->ttype){
39 38
 	case T_VOID:
40
-		fprintf(fp, "void%s%s", name? " " : "", name ? : "");
39
+	print_void:
40
+		fprintf(fp, "\e[2mvoid\e[0m%s%s", name? " " : "", name ? : "");
41 41
 		break;
42 42
 	case T_TYPEDEF:
43
-		fprintf(fp, "%s%s%s", t->tdef.name, name? " " : "", name ? : "");
43
+		fprintf(fp, "\e[2m%s\e[0m%s%s", t->tdef.name, name? " " : "", name ? : "");
44 44
 		break;
45 45
 	case T_SCALAR:
46
-		fprintf(fp, "%s%s%s", t->scalar.name, name? " " : "", name ? : "");
46
+		fprintf(fp, "\e[2m%s\e[0m%s%s", t->scalar.name, name? " " : "", name ? : "");
47 47
 		break;
48 48
 	case T_POINTER:
49 49
 		type_dump(t->ptr.type, NULL, fp);
@@ -60,10 +60,10 @@ void type_dump(struct type *t, const char *name, FILE *fp)
60 60
 		type_dump_func(t, name, fp);
61 61
 		break;
62 62
 	case T_MAP:
63
-		fprintf(fp, "map %s[", name ? : "");
64
-		type_dump(t->map.ktype, NULL, fp);
65
-		fputs("] ", fp);
66 63
 		type_dump(t->map.vtype, NULL, fp);
64
+		fprintf(fp, " %s{", name ? : "");
65
+		type_dump(t->map.ktype, NULL, fp);
66
+		fputs("} ", fp);
67 67
 		break;
68 68
 	}
69 69
 }
@@ -179,6 +179,9 @@ static ssize_t type_alignof_struct(struct type *t)
179 179
 
180 180
 ssize_t type_alignof(struct type *t)
181 181
 {
182
+	if (!t)
183
+		return -EINVAL;
184
+
182 185
 	switch (t->ttype){
183 186
 	case T_VOID:
184 187
 	case T_SCALAR:
@@ -245,6 +248,9 @@ ssize_t type_offset_size_of(struct type *t, const char *field)
245 248
 
246 249
 ssize_t type_offsetof(struct type *t, const char *field)
247 250
 {
251
+	if (!t)
252
+		return -EINVAL;
253
+
248 254
 	return type_offset_size_of(t, field);
249 255
 }
250 256
 
@@ -255,6 +261,9 @@ ssize_t type_sizeof_struct(struct type *t)
255 261
 
256 262
 ssize_t type_sizeof(struct type *t)
257 263
 {
264
+	if (!t)
265
+		return -EINVAL;
266
+
258 267
 	switch (t->ttype){
259 268
 	case T_VOID:
260 269
 		return sizeof(void);