3 #include "typecheck_visitor.h"
5 static bool _is_vardecl
= FALSE
;
6 static struct AstNode
*_inside_procfunc
= NULL
;
7 static Symbol
*_procfunc_symbol
= NULL
;
8 static void _typecheck_print_stmt(struct AstNode
*node
, Type type
, const char *ptype_str
);
9 static Symbol
*_complete_symbol_lookup(Symbol
*sym
);
14 Visitor
*visitor
= (Visitor
*) malloc (sizeof(Visitor
));
16 visitor
->visit_program
= &typecheck_visit_program
;
17 visitor
->visit_programdecl
= &typecheck_visit_programdecl
;
18 visitor
->visit_vardecl_list
= &typecheck_visit_vardecl_list
;
19 visitor
->visit_vardecl
= &typecheck_visit_vardecl
;
20 visitor
->visit_procfunc_list
= &typecheck_visit_procfunc_list
;
21 visitor
->visit_procedure
= &typecheck_visit_procfunc
;
22 visitor
->visit_function
= &typecheck_visit_procfunc
;
23 visitor
->visit_param_list
= &typecheck_visit_param_list
;
24 visitor
->visit_parameter
= &typecheck_visit_parameter
;
25 visitor
->visit_statement_list
= &typecheck_visit_statement_list
;
26 visitor
->visit_printint_stmt
= &typecheck_visit_printint_stmt
;
27 visitor
->visit_printchar_stmt
= &typecheck_visit_printchar_stmt
;
28 visitor
->visit_printbool_stmt
= &typecheck_visit_printbool_stmt
;
29 visitor
->visit_printline_stmt
= NULL
;
30 visitor
->visit_assignment_stmt
= &typecheck_visit_assignment_stmt
;
31 visitor
->visit_if_stmt
= &typecheck_visit_if_stmt
;
32 visitor
->visit_while_stmt
= &typecheck_visit_while_stmt
;
33 visitor
->visit_for_stmt
= &typecheck_visit_for_stmt
;
34 visitor
->visit_rel_expr
= &typecheck_visit_binary_expr
;
35 visitor
->visit_add_expr
= &typecheck_visit_binary_expr
;
36 visitor
->visit_mul_expr
= &typecheck_visit_binary_expr
;
37 visitor
->visit_notfactor
= &typecheck_visit_notfactor
;
38 visitor
->visit_call
= &typecheck_visit_call
;
39 visitor
->visit_callparam_list
= &typecheck_visit_callparam_list
;
40 visitor
->visit_callparam
= &typecheck_visit_callparam
;
41 visitor
->visit_identifier_list
= &typecheck_visit_identifier_list
;
42 visitor
->visit_identifier
= &typecheck_visit_identifier
;
43 visitor
->visit_literal
= NULL
;
44 visitor
->visit_add_op
= NULL
;
45 visitor
->visit_mul_op
= NULL
;
46 visitor
->visit_rel_op
= NULL
;
47 visitor
->visit_not_op
= NULL
;
53 typecheck_visit_program(struct _Visitor
*visitor
, struct AstNode
*node
)
56 node
->symbol
= symbol_new(NULL
);
57 global_symtab
= node
->symbol
;
58 symtab
= global_symtab
;
59 _inside_procfunc
= NULL
;
60 ast_node_accept_children(node
->children
, visitor
);
64 typecheck_visit_programdecl (struct _Visitor
*visitor
, struct AstNode
*node
)
67 node
->children
->symbol
->decl_linenum
= node
->linenum
;
68 ast_node_accept(node
->children
, visitor
);
73 typecheck_visit_procfunc_list (struct _Visitor
*visitor
, struct AstNode
*node
)
75 symtab
= global_symtab
;
77 ast_node_accept_children(node
->children
, visitor
);
79 symtab
= global_symtab
;
80 _inside_procfunc
= NULL
;
84 typecheck_visit_procfunc (struct _Visitor
*visitor
, struct AstNode
*node
)
86 struct AstNode
*ident
;
87 struct AstNode
*child
;
89 _inside_procfunc
= node
;
90 _procfunc_symbol
= node
->children
->symbol
;
93 symtab
= global_symtab
;
94 ident
= node
->children
;
97 ident
->symbol
->is_procfunc
= TRUE
;
98 ident
->symbol
->decl_linenum
= node
->linenum
;
100 ast_node_accept(ident
, visitor
);
102 symtab
= node
->symbol
;
104 // ParamList, VarDeclList, Statements
105 for (child
= ident
->sibling
; child
!= NULL
; child
= child
->sibling
) {
106 ast_node_accept(child
, visitor
);
107 if (child
->kind
== PARAM_LIST
)
108 ident
->symbol
->params
= child
->child_counter
;
113 typecheck_visit_vardecl_list (struct _Visitor
*visitor
, struct AstNode
*node
)
115 struct AstNode
*child
;
119 for (child
= node
->children
; child
!= NULL
; child
= child
->sibling
)
120 ast_node_accept(child
, visitor
);
126 typecheck_visit_vardecl (struct _Visitor
*visitor
, struct AstNode
*node
)
128 node
->children
->type
= node
->type
;
129 ast_node_accept(node
->children
, visitor
);
133 typecheck_visit_param_list(struct _Visitor
*visitor
, struct AstNode
*node
)
136 struct AstNode
*child
;
140 node
->child_counter
= 0;
141 for (child
= node
->children
; child
!= NULL
; child
= child
->sibling
) {
142 ast_node_accept(child
, visitor
);
143 node
->child_counter
++;
146 child
= node
->children
;
147 _procfunc_symbol
->param_types
= (int *) malloc
148 (sizeof(int) * node
->child_counter
);
150 for (i
= 0; i
< node
->child_counter
; i
++) {
151 _procfunc_symbol
->param_types
[i
] = child
->type
;
152 child
= child
->sibling
;
155 _procfunc_symbol
->params
= node
->child_counter
;
161 typecheck_visit_parameter (struct _Visitor
*visitor
, struct AstNode
*node
)
163 node
->children
->type
= node
->type
;
164 node
->children
->symbol
->is_parameter
= TRUE
;
165 node
->children
->symbol
->decl_linenum
= node
->linenum
;
166 ast_node_accept(node
->children
, visitor
);
170 typecheck_visit_statement_list(struct _Visitor
*visitor
, struct AstNode
*node
)
172 ast_node_accept_children(node
->children
, visitor
);
176 typecheck_visit_printint_stmt (struct _Visitor
*visitor
, struct AstNode
*node
)
178 ast_node_accept(node
->children
, visitor
);
179 _typecheck_print_stmt(node
, INTEGER
, "Int");
183 typecheck_visit_printchar_stmt (struct _Visitor
*visitor
, struct AstNode
*node
)
185 ast_node_accept(node
->children
, visitor
);
186 _typecheck_print_stmt(node
, CHAR
, "Char");
190 typecheck_visit_printbool_stmt (struct _Visitor
*visitor
, struct AstNode
*node
)
192 ast_node_accept(node
->children
, visitor
);
193 _typecheck_print_stmt(node
, BOOLEAN
, "Bool");
197 typecheck_visit_assignment_stmt (struct _Visitor
*visitor
, struct AstNode
*node
)
199 struct AstNode
*lnode
= node
->children
;
200 struct AstNode
*rnode
= lnode
->sibling
;
202 ast_node_accept(lnode
, visitor
);
203 ast_node_accept(rnode
, visitor
);
205 if (lnode
->symbol
->is_procfunc
&& (_inside_procfunc
== NULL
||
206 strcmp(_inside_procfunc
->children
->symbol
->name
,
207 lnode
->symbol
->name
))) {
210 "Error: Symbol '%s' is a function identifier, you cannot "
211 "assign a value to it from outside the said function. "
212 "Check line %d.\n", lnode
->symbol
->name
, node
->linenum
);
214 } else if (lnode
->type
!= ERROR
&& rnode
->type
!= ERROR
&&
215 lnode
->type
!= rnode
->type
) {
218 "Error: Incompatible types on assignment "
219 "operation in line %d.\n", node
->linenum
);
224 typecheck_visit_if_stmt (struct _Visitor
*visitor
, struct AstNode
*node
)
226 struct AstNode
*expr
= node
->children
;
227 struct AstNode
*stmt
= expr
->sibling
;
229 ast_node_accept(expr
, visitor
);
230 ast_node_accept(stmt
, visitor
);
232 if (expr
->type
!= BOOLEAN
) {
235 "Error: Condition for if statement must be of Boolean type. "
236 "Check line %d.\n", node
->linenum
);
241 typecheck_visit_while_stmt (struct _Visitor
*visitor
, struct AstNode
*node
)
243 struct AstNode
*expr
= node
->children
;
244 struct AstNode
*stmt
= expr
->sibling
;
246 ast_node_accept(expr
, visitor
);
247 ast_node_accept(stmt
, visitor
);
249 if (expr
->type
!= BOOLEAN
) {
252 "Error: Expression in While statement must be of "
253 "Boolean type. Check line %d.\n", expr
->linenum
);
258 typecheck_visit_for_stmt (struct _Visitor
*visitor
, struct AstNode
*node
)
260 struct AstNode
*asgn
= node
->children
;
261 struct AstNode
*expr
= asgn
->sibling
;
262 struct AstNode
*stmt
= expr
->sibling
;
263 struct AstNode
*id_node
= asgn
->children
;
265 ast_node_accept(asgn
, visitor
);
266 ast_node_accept(expr
, visitor
);
268 if (id_node
->type
!= INTEGER
) {
271 "Error: Identifier '%s' is of %s type; it must be Integer. "
272 "Check line %d.\n", id_node
->symbol
->name
,
273 type_get_lexeme(id_node
->type
), id_node
->linenum
);
276 if (expr
->type
!= INTEGER
) {
279 "Error: Value of stop condition is not of Integer type. "
280 "Check line %d.\n", expr
->linenum
);
283 ast_node_accept(stmt
, visitor
);
288 typecheck_visit_binary_expr (struct _Visitor
*visitor
, struct AstNode
*node
)
290 struct AstNode
*lnode
= node
->children
;
291 struct AstNode
*op
= lnode
->sibling
;
292 struct AstNode
*rnode
= op
->sibling
;
294 ast_node_accept(lnode
, visitor
);
295 ast_node_accept(rnode
, visitor
);
297 if (lnode
->type
!= ERROR
&& rnode
->type
!= ERROR
&&
298 lnode
->type
!= rnode
->type
) {
301 "Error: Operation '%s' over incompatible types on line %d.\n",
302 op
->name
, op
->linenum
);
307 typecheck_visit_notfactor (struct _Visitor
*visitor
, struct AstNode
*node
)
309 ast_node_accept(node
->children
, visitor
);
311 if (node
->children
->type
!= BOOLEAN
) {
314 "Error: Operation 'not' over non-boolean "
315 "operand on line %d.\n", node
->linenum
);
320 typecheck_visit_call (struct _Visitor
*visitor
, struct AstNode
*node
)
323 Symbol
*previous_procfunc
;
324 struct AstNode
*ident
= node
->children
;
325 struct AstNode
*plist
= ident
->sibling
;
327 ast_node_accept(ident
, visitor
);
329 previous_procfunc
= _procfunc_symbol
;
330 _procfunc_symbol
= ident
->symbol
;
331 node
->type
= _procfunc_symbol
->type
;
333 ast_node_accept(plist
, visitor
);
335 params
= (plist
== NULL
) ? 0 : plist
->child_counter
;
336 if (params
!= ident
->symbol
->params
) {
338 fprintf(stderr
, "Error: Expecting %d parameters, received %d. "
340 ident
->symbol
->params
, params
, node
->linenum
);
343 _procfunc_symbol
= previous_procfunc
;
347 typecheck_visit_callparam_list (struct _Visitor
*visitor
, struct AstNode
*node
)
350 struct AstNode
*child
;
352 node
->child_counter
= 0;
353 for (child
= node
->children
; child
!= NULL
; child
= child
->sibling
)
354 node
->child_counter
++;
356 if (_procfunc_symbol
->params
!= node
->child_counter
) {
362 for (child
= node
->children
; child
!= NULL
; child
= child
->sibling
) {
363 ast_node_accept(child
, visitor
);
365 if (child
->type
!= _procfunc_symbol
->param_types
[i
]) {
367 fprintf(stderr
, "Error: Call '%s' on line %d, expecting %s "
369 _procfunc_symbol
->name
, node
->linenum
,
370 type_get_lexeme(_procfunc_symbol
->param_types
[i
]),
373 if (child
->children
->symbol
!= NULL
)
374 fprintf(stderr
, "'%s'", child
->children
->symbol
->name
);
376 value_print(stderr
, &child
->value
, child
->type
);
378 fprintf(stderr
, "), received %s.\n", type_get_lexeme(child
->type
));
385 typecheck_visit_callparam (struct _Visitor
*visitor
, struct AstNode
*node
)
387 ast_node_accept(node
->children
, visitor
);
388 node
->type
= node
->children
->type
;
392 typecheck_visit_identifier_list (struct _Visitor
*visitor
, struct AstNode
*node
)
394 struct AstNode
*child
;
396 for (child
= node
->children
; child
!= NULL
; child
= child
->sibling
) {
397 child
->type
= node
->type
;
398 child
->symbol
->decl_linenum
= node
->linenum
;
399 ast_node_accept(child
, visitor
);
404 typecheck_visit_identifier (struct _Visitor
*visitor
, struct AstNode
*node
)
408 //fprintf(stderr, "====== identifier[%s(gl?%d)]->decl_linenum: %d\n",
409 // node->symbol->name, (symtab==global_symtab), node->symbol->decl_linenum);
413 if (sym == NULL && node->symbol->decl_linenum > 0) {
414 node->symbol->type = node->type;
415 node->symbol->is_global = (symtab == global_symtab);
417 sym = symbol_insert(symtab, node->symbol);
419 if (sym != node->symbol) {
421 fprintf(stderr, "Error: Symbol '%s' already defined in line %d. "
423 sym->name, sym->decl_linenum, node->linenum);
425 node->type = node->symbol->type;
426 node->symbol->decl_linenum = node->linenum;
430 sym = _complete_symbol_lookup(node->symbol);
434 node->type = sym->type;
437 node->symbol->decl_linenum = 0;
439 fprintf(stderr, "Error: Undeclared symbol '%s' in line %d\n",
440 node->symbol->name, node->linenum);
445 sym
= symbol_lookup(symtab
, node
->symbol
->name
);
448 if (node
->symbol
->decl_linenum
> 0) {
449 node
->symbol
->type
= node
->type
;
450 node
->symbol
->is_global
= (symtab
== global_symtab
);
452 sym
= symbol_insert(symtab
, node
->symbol
);
456 fprintf(stderr
, "Error: Undeclared symbol '%s' in line %d\n",
457 node
->symbol
->name
, node
->linenum
);
460 } else if (node
->symbol
->decl_linenum
== 0) {
461 symbol_table_destroy(node
->symbol
);
463 node
->type
= sym
->type
;
467 fprintf(stderr
, "Error: Symbol '%s' already defined in line %d. "
469 sym
->name
, sym
->decl_linenum
, node
->linenum
);
474 // Helper functions ----------------------------------------------------------
477 _typecheck_print_stmt(struct AstNode
*node
, Type type
, const char *ptype_str
)
479 if (node
->children
->type
!= type
) {
482 "Error: Expression Print%s statement must be of "
483 "%s type. Check line %d.\n",
484 ptype_str
, type_get_lexeme(type
), node
->linenum
);