Tobias Waldekranz.com 8 年之前
父节点
当前提交
ad5d87a1da
共有 11 个文件被更改,包括 302 次插入33 次删除
  1. 1 0
      Makefile
  2. 1 1
      arch-x86_64.c
  3. 58 0
      func.c
  4. 51 7
      global.c
  5. 2 2
      ply.c
  6. 126 0
      printxf.c
  7. 25 0
      printxf.h
  8. 7 0
      printxf_test.c
  9. 24 16
      type.c
  10. 5 5
      type.h
  11. 2 2
      type_test.c

+ 1 - 0
Makefile

14
 
14
 
15
 arch-x86_64_test: arch-x86_64_test.o arch-x86_64.o type.o
15
 arch-x86_64_test: arch-x86_64_test.o arch-x86_64.o type.o
16
 type_test: type_test.o type.o
16
 type_test: type_test.o type.o
17
+printxf_test: printxf_test.o printxf.o
17
 
18
 
18
 check: $(cprogs)
19
 check: $(cprogs)
19
 	$(foreach prog,$(cprogs),./$(prog);)
20
 	$(foreach prog,$(cprogs),./$(prog);)

+ 1 - 1
arch-x86_64.c

39
 	{ .name = "rsp",      .type = &t_ulong },
39
 	{ .name = "rsp",      .type = &t_ulong },
40
 	{ .name = "ss",       .type = &t_ulong },
40
 	{ .name = "ss",       .type = &t_ulong },
41
 
41
 
42
-	{ .type = &t_void }
42
+	{ .type = NULL }
43
 };
43
 };
44
 
44
 
45
 struct type t_pt_regs = {
45
 struct type t_pt_regs = {

+ 58 - 0
func.c

1
+#include <errno.h>
2
+
3
+#include "func.h"
4
+#include "node.h"
5
+#include "sym.h"
6
+#include "type.h"
7
+
8
+int func_validate_expr(const struct func *func, struct node *n, int strict)
9
+{
10
+	struct tfield *f;
11
+	struct node *arg;
12
+	int nargs = 0;
13
+
14
+	for (f = func->type->func.args, arg = n->expr.args;
15
+	     f && arg; f++, arg = arg->next, nargs++) {
16
+		if ((!strict && (arg->sym->type->ttype == T_VOID))
17
+		    || (f->type->ttype == T_VOID)
18
+		    || type_compatible(arg->sym->type, f->type) )
19
+			continue;
20
+
21
+		node_error(n, stderr, "type mismatch for argument %d, expected %T, got %T",
22
+			   nargs, f->type, arg->sym->type);
23
+	}
24
+
25
+	return 0;
26
+}
27
+
28
+int func_static_validate(const struct func *func, struct node *n)
29
+{
30
+	if ((n->ntype == N_NUM) || (n->ntype == N_STRING)) {
31
+	}
32
+
33
+	switch (n->ntype) {
34
+	case N_EXPR:
35
+		if (func->type->ttype != T_FUNC) {
36
+			node_error(n, stderr, "'%s' is not callable",
37
+				   n->expr.func);
38
+			return -EINVAL;
39
+		}
40
+		return func_validate_expr(func, n, 0);
41
+
42
+	case N_IDENT:
43
+		if (func->type->ttype == T_FUNC) {
44
+			node_error(n, stderr, "'%s' is a function",
45
+				   n->ident.name);
46
+			return -EINVAL;
47
+		}
48
+		/* fall-through */
49
+	case N_NUM:
50
+	case N_STRING:
51
+		/* ident, num, str. nothing to validate. just copy
52
+		 * type info to the symbol if statically known */
53
+		n->sym->type = func->type;
54
+		break;
55
+	}
56
+
57
+	return 0;
58
+}

+ 51 - 7
global.c

12
 #include "type.h"
12
 #include "type.h"
13
 
13
 
14
 
14
 
15
+/* :map */
16
+
15
 static struct type *global_map_ktype(struct node *n)
17
 static struct type *global_map_ktype(struct node *n)
16
 {
18
 {
17
 	struct node *map, *key;
19
 	struct node *map, *key;
22
 
24
 
23
 	map = n->expr.args;
25
 	map = n->expr.args;
24
 
26
 
25
-	if (node_nargs(n) == 2)
27
+	if (nargs == 2)
26
 		return map->next->sym->type;
28
 		return map->next->sym->type;
27
 
29
 
28
 	ktype = calloc(1, sizeof(*ktype));
30
 	ktype = calloc(1, sizeof(*ktype));
36
 		f->type = key->sym->type;
38
 		f->type = key->sym->type;
37
 	}
39
 	}
38
 
40
 
39
-	f->type = &t_void;
40
-
41
 	asprintf(&ktype->sou.name, ":%s_key", map->ident.name);
41
 	asprintf(&ktype->sou.name, ":%s_key", map->ident.name);
42
 	ktype->ttype = T_STRUCT;
42
 	ktype->ttype = T_STRUCT;
43
 	ktype->sou.fields = kfields;
43
 	ktype->sou.fields = kfields;
46
 	return ktype;
46
 	return ktype;
47
 }
47
 }
48
 
48
 
49
+static int global_map_type_infer(struct prog *prog, struct node *n)
50
+{
51
+	struct node *map = n->expr.args;
52
+
53
+	if (n->sym->type || !map->sym->type)
54
+		return 0;
55
+
56
+	assert(map->sym->type->ttype == T_MAP);
57
+
58
+	/* given `m[key]` where m's type is known, infer that the
59
+	 * expression's type is equal to m's value type. */
60
+	n->sym->type = map->sym->type->map.vtype;
61
+	return 0;
62
+}
63
+
64
+static int global_map_static_verify(struct node *n)
65
+{
66
+	int nargs = node_nargs(n);
67
+
68
+	if (nargs < 2) {
69
+		node_error(n, stderr, "map without key");
70
+		return -EINVAL;
71
+	}
72
+
73
+	if (n->expr.args->ntype != N_IDENT) {
74
+		node_error(n, stderr, "map must be identifier");
75
+		return -EINVAL;
76
+	}
77
+
78
+	return 0;
79
+}
80
+
81
+/* :assign */
82
+
49
 static int global_assign_type_infer_map(struct node *n)
83
 static int global_assign_type_infer_map(struct node *n)
50
 {
84
 {
51
 	struct node *map, *key;
85
 	struct node *map, *key;
73
 		return 0;
107
 		return 0;
74
 
108
 
75
 	if (!lval->sym->type) {
109
 	if (!lval->sym->type) {
110
+		/* given `a = b` where b's type is known but not a's,
111
+		 * infer that a's type must be equal to b's */
76
 		lval->sym->type = rval->sym->type;
112
 		lval->sym->type = rval->sym->type;
77
 
113
 
78
 		if (node_is_map(lval))
114
 		if (node_is_map(lval))
115
 	return -EINVAL;
151
 	return -EINVAL;
116
 }
152
 }
117
 
153
 
154
+
155
+/* pid */
156
+
118
 struct type t_pid = {
157
 struct type t_pid = {
119
 	.ttype = T_TYPEDEF,
158
 	.ttype = T_TYPEDEF,
120
 
159
 
121
 	.tdef = { .name = ":pid", .type = &t_u32 },
160
 	.tdef = { .name = ":pid", .type = &t_u32 },
122
 };
161
 };
123
 
162
 
163
+
164
+/* time */
165
+
124
 struct type t_time = {
166
 struct type t_time = {
125
-	.ttype = T_TYPEDEF,
167
+	.ttype = T_TYPEDEF,	/* TODO: should be a T_FUNC with a static
168
+				 * signature */
126
 
169
 
127
 	.tdef = { .name = ":time", .type = &t_s64 },
170
 	.tdef = { .name = ":time", .type = &t_s64 },
128
 };
171
 };
129
 
172
 
173
+
130
 static const struct func global_funcs[] = {
174
 static const struct func global_funcs[] = {
131
 	{ .name = ":block", .type = &t_void, },
175
 	{ .name = ":block", .type = &t_void, },
132
 
176
 
135
 	
179
 	
136
 	{
180
 	{
137
 		.name = ":assign",
181
 		.name = ":assign",
138
-		.static_verify = global_assign_static_verify,
139
 		.type_infer = global_assign_type_infer,
182
 		.type_infer = global_assign_type_infer,
183
+		.static_verify = global_assign_static_verify,
140
 	},
184
 	},
141
 	{
185
 	{
142
 		.name = ":map",
186
 		.name = ":map",
143
-		/* .static_verify = global_map_static_verify, */
144
-		/* .type_infer = global_map_type_infer, */
187
+		.type_infer = global_map_type_infer,
188
+		.static_verify = global_map_static_verify,
145
 	},
189
 	},
146
 
190
 
147
 	{ .name = "pid",  .type = &t_pid, },
191
 	{ .name = "pid",  .type = &t_pid, },

+ 2 - 2
ply.c

529
 	printf("\n\n-- globals\n");
529
 	printf("\n\n-- globals\n");
530
 	symtab_dump(ctx->globals, stdout);
530
 	symtab_dump(ctx->globals, stdout);
531
 
531
 
532
-	printf("\n\n-- decls\n");
533
-	type_dump_decls(stdout);
532
+	/* printf("\n\n-- decls\n"); */
533
+	/* type_dump_decls(stdout); */
534
 
534
 
535
 	if (err)
535
 	if (err)
536
 		printf("ERR: %d\n", err);
536
 		printf("ERR: %d\n", err);

+ 126 - 0
printxf.c

1
+#include <stdarg.h>
2
+#include <stdint.h>
3
+#include <stdio.h>
4
+#include <stdlib.h>
5
+#include <string.h>
6
+
7
+#include "printxf.h"
8
+
9
+struct printxf printxf_default;
10
+
11
+/* allow domains an easy way to defer standard specifiers to the
12
+ * system's implementation. */
13
+int printxf_vfprintf(struct printxf *pxf,
14
+		     FILE *fp, const char *spec, va_list ap)
15
+{
16
+	return vfprintf(fp, spec, ap);
17
+}
18
+
19
+int __printxf_wsegment(FILE *fp, const char **fmt, size_t ssize, size_t *tsize)
20
+{
21
+	size_t wsize;
22
+
23
+	wsize = fwrite(*fmt, 1, ssize, fp);
24
+	*tsize += wsize;
25
+	*fmt   += wsize;
26
+
27
+	return (wsize < ssize) ? EOF : 0;
28
+}
29
+
30
+int vfprintxf(struct printxf *pxf, FILE *fp, const char *fmt, va_list ap)
31
+{
32
+	size_t tsize = 0, wsize, ssize;
33
+	vfprintxf_fn handler;
34
+	char spec[16];
35
+
36
+	pxf = pxf ? : &printxf_default;
37
+
38
+	if (!fmt)
39
+		return 0;
40
+
41
+	while (*fmt) {
42
+		ssize = strcspn(fmt, "%");
43
+
44
+		/* leading segment containing no format specifiers. */
45
+		if (ssize && __printxf_wsegment(fp, &fmt, ssize, &tsize))
46
+			break;
47
+
48
+		if (fmt[0] == '\0') {
49
+			/* this was the last segment */
50
+			break;
51
+		} else if ((fmt[0] == '%')
52
+			   && ((fmt[1] == '\0') || (fmt[1] == '%'))) {
53
+			/* "%" or "%%", write "%" */
54
+			if (!fwrite("%", 1, 1, fp))
55
+				break;
56
+
57
+			tsize++;
58
+			fmt += fmt[1] ? 2 : 1;
59
+			continue;
60
+		}
61
+		
62
+		ssize = strspn(fmt + 1, " #$'*+,-.0123456789:;L_hjlqtvz") + 1;
63
+
64
+		if (!fmt[ssize]) {
65
+			/* corner case. fmt ends with an unterminated
66
+			 * format. e.g. "evilness: 100%" */
67
+			__printxf_wsegment(fp, &fmt, ssize, &tsize);
68
+			break;
69
+		}
70
+
71
+		handler = pxf->vfprintxf[fmt[ssize] & 0x7f];
72
+		if (!handler) {
73
+			/* unsupported specifier, write the entire
74
+			 * specifier unformatted to the output */
75
+			if (__printxf_wsegment(fp, &fmt, ssize + 1, &tsize))
76
+				break;
77
+
78
+			continue;
79
+		}
80
+
81
+		ssize++;
82
+		memset(spec, '\0', sizeof(spec));
83
+		strncpy(spec, fmt, (ssize >= sizeof(spec)) ? sizeof(spec) - 1 : ssize);
84
+		fmt += ssize;
85
+
86
+		tsize += handler(pxf, fp, spec, ap);
87
+	}
88
+
89
+	return tsize;
90
+}
91
+
92
+int fprintxf(struct printxf *pxf, FILE *fp, const char *fmt, ...)
93
+{
94
+	va_list ap;
95
+	int ret;
96
+
97
+	va_start(ap, fmt);
98
+	ret = vfprintxf(pxf, fp, fmt, ap);
99
+	va_end(ap);
100
+	return ret;
101
+}
102
+
103
+int vprintxf(struct printxf *pxf, const char *fmt, va_list ap)
104
+{
105
+	return vfprintxf(pxf, stdout, fmt, ap);
106
+}
107
+
108
+int printxf(struct printxf *pxf, const char *fmt, ...)
109
+{
110
+	va_list ap;
111
+	int ret;
112
+
113
+	va_start(ap, fmt);
114
+	ret = vprintxf(pxf, fmt, ap);
115
+	va_end(ap);
116
+	return ret;
117
+}
118
+
119
+__attribute__((constructor))
120
+static void printxf_init(void)
121
+{
122
+	const char *std = "aAcdeEfFgGiosuxX";
123
+
124
+	for (; *std; std++)
125
+		printxf_default.vfprintxf[(int)*std] = &printxf_vfprintf;
126
+}

+ 25 - 0
printxf.h

1
+#ifndef _PRINTXF_H
2
+#define _PRINTXF_H
3
+
4
+#include <stdio.h>
5
+
6
+struct printxf;
7
+
8
+typedef int (*vfprintxf_fn)(struct printxf *pxf,
9
+			    FILE *fp, const char *spec, va_list ap);
10
+
11
+extern int printxf_vfprintf(struct printxf *pxf,
12
+			    FILE *fp, const char *spec, va_list ap);
13
+
14
+struct printxf {
15
+	vfprintxf_fn vfprintxf[0x80];
16
+};
17
+
18
+extern struct printxf printxf_default;
19
+
20
+int vfprintxf(struct printxf *pxf, FILE *stream, const char *fmt, va_list ap);
21
+int  fprintxf(struct printxf *pxf, FILE *stream, const char *fmt, ...);
22
+int  vprintxf(struct printxf *pxf,               const char *fmt, va_list ap);
23
+int   printxf(struct printxf *pxf,               const char *fmt, ...);
24
+
25
+#endif	/* _PRINTXF_H */

+ 7 - 0
printxf_test.c

1
+#include "printxf.h"
2
+
3
+
4
+int main(void)
5
+{
6
+	printxf(NULL, "testing %% %.*s %d\n", 3, "w000t", 13);
7
+}

+ 24 - 16
type.c

1
 #include <assert.h>
1
 #include <assert.h>
2
 #include <errno.h>
2
 #include <errno.h>
3
+#include <stdarg.h>
3
 #include <stdio.h>
4
 #include <stdio.h>
4
 #include <stdlib.h>
5
 #include <stdlib.h>
5
 #include <string.h>
6
 #include <string.h>
6
 
7
 
8
+#include "printxf.h"
7
 #include "type.h"
9
 #include "type.h"
8
 
10
 
9
 static void __sgr(FILE *fp, int sgr, const char *s)
11
 static void __sgr(FILE *fp, int sgr, const char *s)
37
 		return;
39
 		return;
38
 	}
40
 	}
39
 
41
 
40
-	for (arg = t->func.args; arg->type != T_VOID; arg++) {
42
+	tfields_foreach(arg, t->func.args) {
41
 		if (arg != t->func.args)
43
 		if (arg != t->func.args)
42
 			fputs(", ", fp);
44
 			fputs(", ", fp);
43
 
45
 
49
 
51
 
50
 void type_dump(struct type *t, const char *name, FILE *fp)
52
 void type_dump(struct type *t, const char *name, FILE *fp)
51
 {
53
 {
52
-	if (!t)
53
-		goto print_void;
54
-
54
+	if (!t) {
55
+		__faint(fp, "(none)");
56
+		goto print_name;
57
+	}
55
 
58
 
56
 	switch (t->ttype){
59
 	switch (t->ttype){
57
 	case T_VOID:
60
 	case T_VOID:
58
-	print_void:
59
 		__faint(fp, "void");
61
 		__faint(fp, "void");
60
-		fputs(name ? " " : "", fp);
61
-		__bold(fp, name);
62
 		break;
62
 		break;
63
 	case T_TYPEDEF:
63
 	case T_TYPEDEF:
64
 		__faint(fp, t->tdef.name);
64
 		__faint(fp, t->tdef.name);
65
-		fputs(name ? " " : "", fp);
66
-		__bold(fp, name);
67
 		break;
65
 		break;
68
 	case T_SCALAR:
66
 	case T_SCALAR:
69
 		__faint(fp, t->scalar.name);
67
 		__faint(fp, t->scalar.name);
70
-		fputs(name ? " " : "", fp);
71
-		__bold(fp, name);
72
 		break;
68
 		break;
73
 	case T_POINTER:
69
 	case T_POINTER:
74
 		type_dump(t->ptr.type, NULL, fp);
70
 		type_dump(t->ptr.type, NULL, fp);
75
 		fputs(" *", fp);
71
 		fputs(" *", fp);
76
 		__bold(fp, name);
72
 		__bold(fp, name);
77
-		break;
73
+		return;
78
 	case T_ARRAY:
74
 	case T_ARRAY:
79
 		type_dump(t->array.type, NULL, fp);
75
 		type_dump(t->array.type, NULL, fp);
80
 		fputs(name ? " " : "", fp);
76
 		fputs(name ? " " : "", fp);
81
 		__bold(fp, name);
77
 		__bold(fp, name);
82
 		fprintf(fp, "[%zu]", t->array.len);
78
 		fprintf(fp, "[%zu]", t->array.len);
83
-		break;
79
+		return;
84
 	case T_STRUCT:
80
 	case T_STRUCT:
85
 		fputs("struct ", fp);
81
 		fputs("struct ", fp);
86
 		__faint(fp, t->sou.name);
82
 		__faint(fp, t->sou.name);
87
-		__bold(fp, name);
88
 		break;
83
 		break;
89
 	case T_FUNC:
84
 	case T_FUNC:
90
 		type_dump_func(t, name, fp);
85
 		type_dump_func(t, name, fp);
91
-		break;
86
+		return;
92
 	case T_MAP:
87
 	case T_MAP:
93
 		type_dump(t->map.vtype, NULL, fp);
88
 		type_dump(t->map.vtype, NULL, fp);
94
 		fputs(name ? " " : "", fp);		
89
 		fputs(name ? " " : "", fp);		
96
 		fputc('{', fp);
91
 		fputc('{', fp);
97
 		type_dump(t->map.ktype, NULL, fp);
92
 		type_dump(t->map.ktype, NULL, fp);
98
 		fputc('}', fp);
93
 		fputc('}', fp);
99
-		break;
94
+		return;
100
 	}
95
 	}
96
+print_name:
97
+	fputs(name ? " " : "", fp);
98
+	__bold(fp, name);
101
 }
99
 }
102
 
100
 
103
 static void type_dump_decl_sou(struct type *t, FILE *fp)
101
 static void type_dump_decl_sou(struct type *t, FILE *fp)
138
 	}
136
 	}
139
 }
137
 }
140
 
138
 
139
+int type_vfprintxf(struct printxf *pxf, FILE *fp, const char *spec, va_list ap)
140
+{
141
+	struct type *t;
142
+
143
+	t = va_arg(ap, struct type *);
144
+	type_dump(t, NULL, fp);
145
+	return 0;
146
+}
141
 
147
 
142
 struct type *type_normalize(struct type *t)
148
 struct type *type_normalize(struct type *t)
143
 {
149
 {
492
 static void type_init(void)
498
 static void type_init(void)
493
 {
499
 {
494
 	type_add_list(builtin_types);
500
 	type_add_list(builtin_types);
501
+
502
+	printxf_default.vfprintxf['T'] = type_vfprintxf;
495
 }
503
 }

+ 5 - 5
type.h

33
 struct tfield {
33
 struct tfield {
34
 	char *name;
34
 	char *name;
35
 	struct type *type;
35
 	struct type *type;
36
-
37
-	/* function arguments */
38
-	int optional:1;
39
 };
36
 };
40
 
37
 
41
 #define tfields_foreach(_f, _fields) \
38
 #define tfields_foreach(_f, _fields) \
42
-	for ((_f) = (_fields); (_f)->type->ttype != T_VOID; (_f)++)
39
+	for ((_f) = (_fields); (_f)->type; (_f)++)
43
 
40
 
44
 struct tstruct {
41
 struct tstruct {
45
 	char *name;
42
 	char *name;
43
+	struct tfield *fields;
46
 
44
 
47
 	int packed:1;
45
 	int packed:1;
48
-	struct tfield *fields;
49
 };
46
 };
50
 
47
 
51
 struct tfunc {
48
 struct tfunc {
52
 	struct type *type;
49
 	struct type *type;
53
 	struct tfield *args;
50
 	struct tfield *args;
51
+
52
+	int vargs:1;
53
+	int aggregation:1;
54
 };
54
 };
55
 
55
 
56
 enum ttype {
56
 enum ttype {

+ 2 - 2
type_test.c

62
 		{ .name = "c", .type = type_array_of(&t_char, 3) },
62
 		{ .name = "c", .type = type_array_of(&t_char, 3) },
63
 		{ .name = "d", .type = &t_short },
63
 		{ .name = "d", .type = &t_short },
64
 
64
 
65
-		{ .type = &t_void }
65
+		{ .type = NULL }
66
 	};
66
 	};
67
 	struct type t_t1 = {
67
 	struct type t_t1 = {
68
 		.ttype = T_STRUCT,
68
 		.ttype = T_STRUCT,
95
 		{ .name = "c", .type = type_array_of(&t_char, 3) },
95
 		{ .name = "c", .type = type_array_of(&t_char, 3) },
96
 		{ .name = "d", .type = &t_short },
96
 		{ .name = "d", .type = &t_short },
97
 
97
 
98
-		{ .type = &t_void }
98
+		{ .type = NULL }
99
 	};
99
 	};
100
 	struct type t_t1 = {
100
 	struct type t_t1 = {
101
 		.ttype = T_STRUCT,
101
 		.ttype = T_STRUCT,