Must... go...
[toypasc.git] / typecheck_visitor.c
blobf3a27611e1d492b2e9c395773d75006b61b1811f
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include "typecheck_visitor.h"
5 static bool is_vardecl = FALSE;
6 static Symbol *procfunc_symbol = NULL;
7 static Symbol *_symbol_lookup(Symbol *sym);
8 static Type _get_expression_type(struct AstNode *node);
10 Visitor *
11 typecheck_new()
13 Visitor *tc_visitor = (Visitor *) malloc (sizeof(Visitor));
15 tc_visitor->visit_program = &typecheck_visit_program;
16 tc_visitor->visit_programdecl = &typecheck_visit_programdecl;
17 tc_visitor->visit_vardecl_list = &typecheck_visit_vardecl_list;
18 tc_visitor->visit_vardecl = &typecheck_visit_vardecl;
19 tc_visitor->visit_identifier_list = &typecheck_visit_donothing;
20 tc_visitor->visit_procfunc_list = &typecheck_visit_procfunc_list;
21 tc_visitor->visit_procedure = &typecheck_visit_procfunc;
22 tc_visitor->visit_function = &typecheck_visit_procfunc;
23 tc_visitor->visit_param_list = &typecheck_visit_donothing;
24 tc_visitor->visit_parameter = &typecheck_visit_parameter;
25 tc_visitor->visit_statement_list = &typecheck_visit_statement_list;
26 tc_visitor->visit_print_stmt = &typecheck_visit_print_stmt;
27 tc_visitor->visit_assignment_stmt = &typecheck_visit_assignment_stmt;
28 tc_visitor->visit_if_stmt = &typecheck_visit_if_stmt;
29 tc_visitor->visit_while_stmt = &typecheck_visit_while_stmt;
30 tc_visitor->visit_for_stmt = &typecheck_visit_for_stmt;
31 tc_visitor->visit_rel_expr = &typecheck_visit_binary_expr;
32 tc_visitor->visit_add_expr = &typecheck_visit_binary_expr;
33 tc_visitor->visit_mul_expr = &typecheck_visit_binary_expr;
34 tc_visitor->visit_notfactor = &typecheck_visit_notfactor;
35 tc_visitor->visit_call = &typecheck_visit_call;
36 tc_visitor->visit_callparam_list = &typecheck_visit_callparam_list;
37 tc_visitor->visit_identifier = &typecheck_visit_identifier;
38 tc_visitor->visit_literal = &typecheck_visit_donothing;
39 tc_visitor->close_group = NULL;
42 void
43 typecheck_visit_donothing(struct AstNode *node)
47 void
48 typecheck_visit_program(struct AstNode *node)
50 node->symbol = symbol_new(NULL);
51 global_symtab = node->symbol;
52 symtab = global_symtab;
55 void
56 typecheck_visit_programdecl(struct AstNode *node)
58 is_vardecl = TRUE;
61 void
62 typecheck_visit_procfunc_list(struct AstNode *node)
64 symtab = global_symtab;
67 void
68 typecheck_visit_procfunc(struct AstNode *node)
70 is_vardecl = FALSE;
71 symtab = node->symbol;
72 procfunc_symbol = node->children->symbol;
75 void
76 typecheck_visit_vardecl_list (struct AstNode *node)
78 is_vardecl = TRUE;
79 symtab = node->parent->symbol;
82 void
83 typecheck_visit_vardecl (struct AstNode *node)
85 declared_type = node->type;
88 void
89 typecheck_visit_parameter (struct AstNode *node)
91 is_vardecl = TRUE;
92 declared_type = node->type;
95 void
96 typecheck_visit_statement_list(struct AstNode *node)
98 is_vardecl = FALSE;
99 declared_type = VOID;
100 symtab = node->parent->symbol;
103 void
104 typecheck_visit_print_stmt (struct AstNode *node)
108 void
109 typecheck_visit_assignment_stmt (struct AstNode *node)
111 struct AstNode *node1 = node->children;
112 struct AstNode *node2 = node1->sibling;
114 if (node1->kind != IDENTIFIER) {
115 fprintf(stderr,
116 "Error: Left side of assignment must be an Identifier. Check line %d.\n",
117 node->linenum);
118 return;
121 if (_get_expression_type(node1) != _get_expression_type(node2)) {
122 node->type = ERROR;
123 fprintf(stderr,
124 "Error: Incompatible types on assignment operation in line %d.\n",
125 node->linenum);
129 void
130 typecheck_visit_if_stmt (struct AstNode *node)
132 struct AstNode *node1 = node->children;
133 struct AstNode *node2 = node1->sibling;
134 struct AstNode *node3 = node2->sibling;
136 /*if (_get_expression_type(node1) != BOOLEAN) {
137 node->type = ERROR;
138 fprintf(stderr,
139 "Error: Condition for if statement must return a boolean. Check line %d.\n",
140 node->linenum);
144 void
145 typecheck_visit_while_stmt (struct AstNode *node)
149 void
150 typecheck_visit_for_stmt (struct AstNode *node)
154 void
155 typecheck_visit_binary_expr (struct AstNode *node)
157 Type type1;
158 Type type2;
159 Symbol *symbol;
160 struct AstNode *node1 = node->children;
161 struct AstNode *operator = node1->sibling;
162 struct AstNode *node2 = operator->sibling;
164 type1 = _get_expression_type(node1);
165 type2 = _get_expression_type(node2);
167 if (type1 != type2) {
168 node->type = ERROR;
169 fprintf(stderr,
170 "Error: Operation '%s' over incompatible types on line %d.\n",
171 operator->name, operator->linenum);
175 void
176 typecheck_visit_notfactor (struct AstNode *node)
180 void
181 typecheck_visit_call (struct AstNode *node)
183 int i;
184 char *name;
185 Symbol *sym;
187 name = node->children->symbol->name;
188 sym = symbol_lookup(global_symtab, name);
189 procfunc_symbol = sym;
191 if (sym == NULL) {
192 fprintf(stderr,
193 "Error: Undeclared function or procedure '%s' in line %d\n",
194 name, node->linenum);
195 return;
198 node->type = sym->type;
201 void
202 typecheck_visit_callparam_list (struct AstNode *node)
204 int i;
205 struct AstNode *temp;
207 i = 0;
208 for (temp = node->children; temp != NULL; temp = temp->sibling) {
209 if (temp->type != procfunc_symbol->param_types[i]) {
210 fprintf(stderr, "Error: Call '%s' on line %d, expecting %s, received %s.\n",
211 procfunc_symbol->name, node->linenum,
212 type_get_lexeme(procfunc_symbol->param_types[i]),
213 type_get_lexeme(temp->type));
216 i++;
217 if (i > procfunc_symbol->params)
218 break;
220 if (i != procfunc_symbol->params) {
221 fprintf(stderr, "Error: Expecting %d parameters, received %d.\n",
222 i, procfunc_symbol->params);
226 void
227 typecheck_visit_identifier (struct AstNode *node)
229 Symbol *sym;
231 if (is_vardecl) {
232 node->type = declared_type;
233 node->symbol->type = declared_type;
234 sym = symbol_insert(symtab, node->symbol);
236 if (node->parent->kind == PARAMETER) {
237 procfunc_symbol->param_types[procfunc_symbol->params] = node->symbol->type;
238 procfunc_symbol->params++;
241 if (sym != node->symbol)
242 fprintf(stderr, "Error: Symbol '%s' already defined in line XX\n",
243 sym->name);
245 } else if (node->parent->kind == FUNCTION ||
246 node->parent->kind == PROCEDURE) {
247 sym = symbol_insert(global_symtab, node->symbol);
248 node->type = node->symbol->type;
249 node->parent->type = node->type;
250 procfunc_symbol = node->symbol;
252 if (sym != node->symbol)
253 fprintf(stderr, "Error: Symbol '%s' already defined in line XX\n",
254 sym->name);
256 } else {
257 sym = _symbol_lookup(node->symbol);
259 if (sym != NULL)
260 node->symbol = sym;
261 else {
262 node->symbol->decl_linenum = 0;
263 fprintf(stderr, "Error: Undeclared symbol '%s' in line %d\n",
264 node->symbol->name, node->linenum);
267 if (node->parent->kind == CALLPARAM_LIST) {
268 int i;
269 //procfunc_symbol->param_types[procfunc_symbol->params] = node->symbol->type;
270 //procfunc_symbol->params++;
271 fprintf(stderr, "Parameter: %s (%x)\n",
272 procfunc_symbol->name, procfunc_symbol);
273 fprintf(stderr, "types (%d): ", procfunc_symbol->params);
274 for (i = 0; i < procfunc_symbol->params; i++) {
275 fprintf(stderr, "%d ",
276 procfunc_symbol->param_types[procfunc_symbol->params]);
278 fprintf(stderr, "\n");
284 static Symbol *
285 _symbol_lookup(Symbol *sym)
287 Symbol *symbol = NULL;
289 symbol = symbol_lookup(symtab, sym->name);
291 if (symbol == NULL)
292 symbol = symbol_lookup(global_symtab, sym->name);
294 return symbol;
297 static Type
298 _get_expression_type(struct AstNode *node)
300 char *name;
301 Symbol *sym;
303 switch (node->kind) {
304 case IDENTIFIER:
305 sym = _symbol_lookup(node->symbol);
306 if (sym != NULL) {
307 node->type = sym->type;
308 return sym->type;
310 break;
312 case INT_LITERAL:
313 case BOOL_LITERAL:
314 case CHAR_LITERAL:
315 return node->type;
317 case NOTFACTOR:
318 return BOOLEAN;
320 case ADD_EXPR:
321 case MUL_EXPR:
322 case REL_EXPR:
323 return INTEGER;
325 case CALL:
326 name = node->children->symbol->name;
327 sym = symbol_lookup(global_symtab, name);
328 if (sym != NULL) {
329 node->type = sym->type;
330 return sym->type;
332 break;
335 return VOID;
338 /*static Type
339 _get_func_type(struct AstNode *node)
341 Symbol *symbol;
342 char *name;
344 if (node->kind != FUNCTION)
345 return VOID;
347 name = node->children->symbol->name;
348 symbol = symbol_lookup(global_symtab, name);
350 if (symbol == NULL) {
351 fprintf(stderr, "Error: Undeclared symbol '%s' in line %d\n",
352 name, node->linenum);
353 return VOID;
356 return symbol->type;