Bläddra i källkod

first tiny program's types are all inferred

Tobias Waldekranz.com 8 år sedan
förälder
incheckning
f112feac82
9 ändrade filer med 86 tillägg och 21 borttagningar
  1. 1 1
      global.c
  2. 1 1
      kprobe.c
  3. 2 0
      node.c
  4. 8 1
      node.h
  5. 34 8
      ply.c
  6. 6 2
      sym.c
  7. 6 3
      sym.h
  8. 27 5
      type.c
  9. 1 0
      type.h

+ 1 - 1
global.c

@@ -86,7 +86,7 @@ int global_resolve(prog_t *prog, node_t *n)
86 86
 	}
87 87
 
88 88
 	n->type = t;
89
-	return sym_add(prog->locals, n->ident, t);
89
+	return sym_add(prog->locals, n->ident, t, &n->sym);
90 90
 }
91 91
 
92 92
 int global_probe(prog_t *prog)

+ 1 - 1
kprobe.c

@@ -29,7 +29,7 @@ int kprobe_resolve(prog_t *prog, node_t *n)
29 29
 		return -ENOENT;
30 30
 
31 31
 	n->type = t;
32
-	return sym_add(prog->locals, n->ident, t);
32
+	return sym_add(prog->locals, n->ident, t, &n->sym);
33 33
 }
34 34
 
35 35
 int kprobe_probe(prog_t *prog)

+ 2 - 0
node.c

@@ -162,6 +162,7 @@ node_t *node_list(node_t *head)
162 162
 	node_t *n = __node(N_LIST);
163 163
 
164 164
 	n->list = head;
165
+	head->up = n;
165 166
 	return n;
166 167
 }
167 168
 
@@ -175,6 +176,7 @@ node_t *node_vlist(node_t *head, ...)
175 176
         va_start(ap, head);
176 177
         while ((next = va_arg(ap, node_t *))) {
177 178
 		insque(next, head);
179
+		next->up = n;
178 180
 		head = next;
179 181
         }
180 182
         va_end(ap);

+ 8 - 1
node.h

@@ -4,6 +4,7 @@
4 4
 #include <stdint.h>
5 5
 #include <stdio.h>
6 6
 
7
+#include "sym.h"
7 8
 #include "type.h"
8 9
 
9 10
 typedef struct node node_t;
@@ -22,7 +23,7 @@ typedef enum ntype {
22 23
 } ntype_t;
23 24
 
24 25
 struct node {
25
-	node_t *next, *prev;
26
+	node_t *next, *prev, *up;
26 27
 
27 28
 	ntype_t ntype;
28 29
 	union {
@@ -34,6 +35,7 @@ struct node {
34 35
 	};
35 36
 
36 37
 	type_t *type;
38
+	sym_t *sym;
37 39
 };
38 40
 
39 41
 /* debug */
@@ -73,4 +75,9 @@ static inline node_t *node_next(node_t *n)
73 75
 	return n ? n->next : NULL;
74 76
 }
75 77
 
78
+static inline node_t *node_up(node_t *n)
79
+{
80
+	return n ? n->up : NULL;
81
+}
82
+
76 83
 #endif	/* _PLY_NODE_H */

+ 34 - 8
ply.c

@@ -102,7 +102,7 @@ int pass_resolve_symbols(node_t *n, void *_prog)
102 102
 
103 103
 	/* neither provider identifier nor global ditto => user
104 104
 	 * variable, add it as a global symbol of unknown type. */
105
-	return sym_add(prog->globals, n->ident, NULL);
105
+	return sym_add(prog->globals, n->ident, NULL, &n->sym);
106 106
 }
107 107
 
108 108
 int infer_type_list(prog_t *prog, node_t *n)
@@ -131,19 +131,27 @@ int infer_type_list(prog_t *prog, node_t *n)
131 131
 
132 132
 int infer_type_keyword(prog_t *prog, node_t *n)
133 133
 {
134
-	node_t *c;
134
+	node_t *dst, *src;
135 135
 
136 136
 	switch (n->keyword) {
137
-	case KW_SUBSCRIPT:
138
-		c = node_next(node_next(n));
139
-		assert(c);
140
-		n->type = c->type;
141
-		return 0;
142 137
 	case KW_ASSIGN:
138
+		dst = node_next(n);
139
+		src = node_next(dst);
140
+		assert(dst && src);
141
+
142
+		if (!src->type)
143
+			return 0;
144
+
145
+		if (!dst->type)
146
+			dst->type = src->type;
147
+
143 148
 		/* TODO: assignment is statement for now. do we need
144 149
 		 * c-style assignment expressions? e.g `a = b = 2;` */
145 150
 		n->type = &t_v;
146 151
 		return 0;
152
+
153
+	default:
154
+		return 0;
147 155
 	}
148 156
 
149 157
 	return -ENOSYS;
@@ -151,7 +159,25 @@ int infer_type_keyword(prog_t *prog, node_t *n)
151 159
 
152 160
 int infer_type_sym(prog_t *prog, node_t *n)
153 161
 {
154
-	printf("WKZ\n");
162
+	node_t *parent, *key;
163
+
164
+	if (n->sym->type)
165
+		return 0;
166
+
167
+	parent = node_up(n);
168
+	key = node_next(n);
169
+
170
+	/* match `somemap[somekey]` where the type of the entire
171
+	 * expression and the type of the key is known, since that
172
+	 * means the type of the map itself is also known. */
173
+	if (parent && parent->type
174
+	    && (parent->list->ntype == N_KEYWORD)
175
+	    && (parent->list->keyword == KW_SUBSCRIPT)
176
+	    && key && key->type) {
177
+		n->type = type_get_map_of(key->type, parent->type);
178
+
179
+		return sym_add(n->sym->st, n->ident, n->type, NULL);
180
+	}
155 181
 
156 182
 	return 0;
157 183
 }

+ 6 - 2
sym.c

@@ -18,7 +18,7 @@ sym_t *sym_get(symtab_t *st, const char *name)
18 18
 	return NULL;
19 19
 }
20 20
 
21
-int sym_add(symtab_t *st, const char *name, type_t *type)
21
+int sym_add(symtab_t *st, const char *name, type_t *type, sym_t **new)
22 22
 {
23 23
 	sym_t *sym;
24 24
 
@@ -31,15 +31,19 @@ int sym_add(symtab_t *st, const char *name, type_t *type)
31 31
 		else if (type && !type_equal(sym->type, type))
32 32
 			return -EINVAL;
33 33
 
34
-		return 0;
34
+		goto found;
35 35
 	}
36 36
 
37 37
 	st->sym = realloc(st->sym, ++st->len * sizeof(*st->sym));
38 38
 	assert(st->sym);
39 39
 
40 40
 	sym = &st->sym[st->len-1];
41
+	sym->st   = st;
41 42
 	sym->name = name;
42 43
 	sym->type = type;
44
+found:
45
+	if (new)
46
+		*new = sym;
43 47
 	return 0;
44 48
 }
45 49
 

+ 6 - 3
sym.h

@@ -3,18 +3,21 @@
3 3
 
4 4
 #include "type.h"
5 5
 
6
+typedef struct symtab symtab_t;
7
+
6 8
 typedef struct sym {
9
+	symtab_t *st;
7 10
 	const char *name;
8 11
 	type_t *type;
9 12
 } sym_t;
10 13
 
11
-typedef struct symtab {
14
+struct symtab {
12 15
 	sym_t *sym;
13 16
 	size_t len;
14
-} symtab_t;
17
+};
15 18
 
16 19
 sym_t *sym_get(symtab_t *st, const char *name);
17
-int    sym_add(symtab_t *st, const char *name, type_t *type);
20
+int    sym_add(symtab_t *st, const char *name, type_t *type, sym_t **new);
18 21
 
19 22
 void sym_dump(sym_t *sym, FILE *fp);
20 23
 void symtab_dump(symtab_t *st, FILE *fp);

+ 27 - 5
type.c

@@ -116,8 +116,10 @@ void type_dump(type_t *t, FILE *fp)
116 116
 		type_dump_func(t, fp);
117 117
 		break;
118 118
 	case T_MAP:
119
-		/* TODO */
120
-		assert(0);
119
+		fputs("map [", fp);
120
+		type_dump(t->t.map.ktype, fp);
121
+		fputs("] ", fp);
122
+		type_dump(t->t.map.vtype, fp);
121 123
 		break;
122 124
 	}
123 125
 }
@@ -172,6 +174,27 @@ void types_dump_cdecl(FILE *fp)
172 174
 	}
173 175
 }
174 176
 
177
+type_t *type_get_map_of(type_t *ktype, type_t *vtype)
178
+{
179
+	type_t *t;
180
+	size_t i;
181
+
182
+	for (i = 0; i < types.len; i++) {
183
+		t = types.type[i];
184
+		if ((t->ttype == T_MAP)
185
+		    && (t->t.map.ktype == ktype)
186
+		    && (t->t.map.vtype == vtype))
187
+			return t;
188
+	}
189
+
190
+	t = calloc(1, sizeof(*t));
191
+	t->ttype = T_MAP;
192
+	t->t.map.vtype = vtype;
193
+	t->t.map.ktype = ktype;
194
+	type_add(t);
195
+	return t;
196
+}
197
+
175 198
 int type_equal(type_t *a, type_t *b)
176 199
 {
177 200
 	/* TODO */
@@ -232,10 +255,9 @@ void type_size_set(type_t *t)
232 255
 	case T_ARRAY:
233 256
 		t->size = t->t.array.len * t->t.array.type->size;
234 257
 		break;
235
-
236 258
 	case T_MAP:
237
-		/* TODO */
238
-		assert(0);
259
+		/* map fds are s64:s */
260
+		t->size = 8;
239 261
 		break;
240 262
 	}
241 263
 }

+ 1 - 0
type.h

@@ -104,6 +104,7 @@ extern type_t t_llp;
104 104
 extern type_t t_ull;
105 105
 extern type_t t_ullp;
106 106
 
107
+type_t *type_get_map_of(type_t *ktype, type_t *vtype);
107 108
 
108 109
 int type_equal(type_t *a, type_t *b);
109 110
 int type_add(type_t *t);