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
);
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
;
43 typecheck_visit_donothing(struct AstNode
*node
)
48 typecheck_visit_program(struct AstNode
*node
)
50 node
->symbol
= symbol_new(NULL
);
51 global_symtab
= node
->symbol
;
52 symtab
= global_symtab
;
56 typecheck_visit_programdecl(struct AstNode
*node
)
62 typecheck_visit_procfunc_list(struct AstNode
*node
)
64 symtab
= global_symtab
;
68 typecheck_visit_procfunc(struct AstNode
*node
)
71 symtab
= node
->symbol
;
72 procfunc_symbol
= node
->children
->symbol
;
76 typecheck_visit_vardecl_list (struct AstNode
*node
)
79 symtab
= node
->parent
->symbol
;
83 typecheck_visit_vardecl (struct AstNode
*node
)
85 declared_type
= node
->type
;
89 typecheck_visit_parameter (struct AstNode
*node
)
92 declared_type
= node
->type
;
96 typecheck_visit_statement_list(struct AstNode
*node
)
100 symtab
= node
->parent
->symbol
;
104 typecheck_visit_print_stmt (struct AstNode
*node
)
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
) {
116 "Error: Left side of assignment must be an Identifier. Check line %d.\n",
121 if (_get_expression_type(node1
) != _get_expression_type(node2
)) {
124 "Error: Incompatible types on assignment operation in line %d.\n",
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) {
139 "Error: Condition for if statement must return a boolean. Check line %d.\n",
145 typecheck_visit_while_stmt (struct AstNode
*node
)
150 typecheck_visit_for_stmt (struct AstNode
*node
)
155 typecheck_visit_binary_expr (struct AstNode
*node
)
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
) {
170 "Error: Operation '%s' over incompatible types on line %d.\n",
171 operator->name
, operator->linenum
);
176 typecheck_visit_notfactor (struct AstNode
*node
)
181 typecheck_visit_call (struct AstNode
*node
)
187 name
= node
->children
->symbol
->name
;
188 sym
= symbol_lookup(global_symtab
, name
);
189 procfunc_symbol
= sym
;
193 "Error: Undeclared function or procedure '%s' in line %d\n",
194 name
, node
->linenum
);
198 node
->type
= sym
->type
;
202 typecheck_visit_callparam_list (struct AstNode
*node
)
205 struct AstNode
*temp
;
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
));
217 if (i
> procfunc_symbol
->params
)
220 if (i
!= procfunc_symbol
->params
) {
221 fprintf(stderr
, "Error: Expecting %d parameters, received %d.\n",
222 i
, procfunc_symbol
->params
);
227 typecheck_visit_identifier (struct AstNode
*node
)
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",
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",
257 sym
= _symbol_lookup(node
->symbol
);
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
) {
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");
285 _symbol_lookup(Symbol
*sym
)
287 Symbol
*symbol
= NULL
;
289 symbol
= symbol_lookup(symtab
, sym
->name
);
292 symbol
= symbol_lookup(global_symtab
, sym
->name
);
298 _get_expression_type(struct AstNode
*node
)
303 switch (node
->kind
) {
305 sym
= _symbol_lookup(node
->symbol
);
307 node
->type
= sym
->type
;
326 name
= node
->children
->symbol
->name
;
327 sym
= symbol_lookup(global_symtab
, name
);
329 node
->type
= sym
->type
;
339 _get_func_type(struct AstNode *node)
344 if (node->kind != FUNCTION)
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);