Adicionando codegen_visitor.h e c
[toypasc.git] / typecheck_visitor.c
blob7c5cc7a007828356e6506641a46c3c0a071baa32
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)
152 Type type;
153 struct AstNode *assign_node = node->children;
154 struct AstNode *id_node = assign_node->children;
155 struct AstNode *expr1_node = id_node->sibling;
156 struct AstNode *expr2_node = assign_node->sibling;
158 type = _get_expression_type(id_node);
159 if (type != INTEGER) {
160 node->type = ERROR;
161 fprintf(stderr,
162 "Error: Identifier '%s' is not of Integer type. "
163 "Check line %d.\n",
164 id_node->symbol->name, id_node->linenum);
166 type = _get_expression_type(expr1_node);
167 if (type != INTEGER) {
168 node->type = ERROR;
169 fprintf(stderr,
170 "Error: Initial value of '%s' is not of Integer type. "
171 "Check line %d.\n",
172 id_node->symbol->name, expr1_node->linenum);
174 type = _get_expression_type(expr1_node);
175 if (type != INTEGER) {
176 node->type = ERROR;
177 fprintf(stderr,
178 "Error: Value of stop condition is not of Integer type. "
179 "Check line %d.\n", expr2_node->linenum);
183 void
184 typecheck_visit_binary_expr (struct AstNode *node)
186 Type type1;
187 Type type2;
188 Symbol *symbol;
189 struct AstNode *node1 = node->children;
190 struct AstNode *operator = node1->sibling;
191 struct AstNode *node2 = operator->sibling;
193 type1 = _get_expression_type(node1);
194 type2 = _get_expression_type(node2);
196 if (type1 != type2) {
197 node->type = ERROR;
198 fprintf(stderr,
199 "Error: Operation '%s' over incompatible types on line %d.\n",
200 operator->name, operator->linenum);
204 void
205 typecheck_visit_notfactor (struct AstNode *node)
209 void
210 typecheck_visit_call (struct AstNode *node)
212 int i;
213 char *name;
214 Symbol *sym;
216 name = node->children->symbol->name;
217 sym = symbol_lookup(global_symtab, name);
218 procfunc_symbol = sym;
220 if (sym == NULL) {
221 fprintf(stderr,
222 "Error: Undeclared function or procedure '%s' in line %d\n",
223 name, node->linenum);
224 return;
227 node->type = sym->type;
230 void
231 typecheck_visit_callparam_list (struct AstNode *node)
233 int i;
234 struct AstNode *temp;
236 i = 0;
237 for (temp = node->children; temp != NULL; temp = temp->sibling) {
238 if (temp->type != procfunc_symbol->param_types[i]) {
239 fprintf(stderr, "Error: Call '%s' on line %d, expecting %s, received %s.\n",
240 procfunc_symbol->name, node->linenum,
241 type_get_lexeme(procfunc_symbol->param_types[i]),
242 type_get_lexeme(temp->type));
245 i++;
246 if (i > procfunc_symbol->params)
247 break;
249 if (i != procfunc_symbol->params) {
250 fprintf(stderr, "Error: Expecting %d parameters, received %d.\n",
251 i, procfunc_symbol->params);
255 void
256 typecheck_visit_identifier (struct AstNode *node)
258 Symbol *sym;
260 if (is_vardecl) {
261 node->type = declared_type;
262 node->symbol->type = declared_type;
263 sym = symbol_insert(symtab, node->symbol);
265 if (node->parent->kind == PARAMETER) {
266 procfunc_symbol->param_types[procfunc_symbol->params] = node->symbol->type;
267 procfunc_symbol->params++;
270 if (sym != node->symbol)
271 fprintf(stderr, "Error: Symbol '%s' already defined in line XX\n",
272 sym->name);
274 } else if (node->parent->kind == FUNCTION ||
275 node->parent->kind == PROCEDURE) {
276 sym = symbol_insert(global_symtab, node->symbol);
277 node->type = node->symbol->type;
278 node->parent->type = node->type;
279 procfunc_symbol = node->symbol;
281 if (sym != node->symbol)
282 fprintf(stderr, "Error: Symbol '%s' already defined in line XX\n",
283 sym->name);
285 } else {
286 sym = _symbol_lookup(node->symbol);
288 if (sym != NULL)
289 node->symbol = sym;
290 else {
291 node->symbol->decl_linenum = 0;
292 fprintf(stderr, "Error: Undeclared symbol '%s' in line %d\n",
293 node->symbol->name, node->linenum);
296 if (node->parent->kind == CALLPARAM_LIST) {
297 int i;
298 //procfunc_symbol->param_types[procfunc_symbol->params] = node->symbol->type;
299 //procfunc_symbol->params++;
300 fprintf(stderr, "Parameter: %s (%x)\n",
301 procfunc_symbol->name, procfunc_symbol);
302 fprintf(stderr, "types (%d): ", procfunc_symbol->params);
303 for (i = 0; i < procfunc_symbol->params; i++) {
304 fprintf(stderr, "%d ",
305 procfunc_symbol->param_types[procfunc_symbol->params]);
307 fprintf(stderr, "\n");
313 static Symbol *
314 _symbol_lookup(Symbol *sym)
316 Symbol *symbol = NULL;
318 symbol = symbol_lookup(symtab, sym->name);
320 if (symbol == NULL)
321 symbol = symbol_lookup(global_symtab, sym->name);
323 return symbol;
326 static Type
327 _get_expression_type(struct AstNode *node)
329 char *name;
330 Symbol *sym;
332 switch (node->kind) {
333 case IDENTIFIER:
334 sym = _symbol_lookup(node->symbol);
335 if (sym != NULL) {
336 node->type = sym->type;
337 return sym->type;
339 break;
341 case INT_LITERAL:
342 case BOOL_LITERAL:
343 case CHAR_LITERAL:
344 return node->type;
346 case NOTFACTOR:
347 return BOOLEAN;
349 case ADD_EXPR:
350 case MUL_EXPR:
351 case REL_EXPR:
352 return INTEGER;
354 case CALL:
355 name = node->children->symbol->name;
356 sym = symbol_lookup(global_symtab, name);
357 if (sym != NULL) {
358 node->type = sym->type;
359 return sym->type;
361 break;
364 return VOID;
367 /*static Type
368 _get_func_type(struct AstNode *node)
370 Symbol *symbol;
371 char *name;
373 if (node->kind != FUNCTION)
374 return VOID;
376 name = node->children->symbol->name;
377 symbol = symbol_lookup(global_symtab, name);
379 if (symbol == NULL) {
380 fprintf(stderr, "Error: Undeclared symbol '%s' in line %d\n",
381 name, node->linenum);
382 return VOID;
385 return symbol->type;