This repository has been archived by the owner on Nov 10, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
make_params.cpp
327 lines (311 loc) · 8.74 KB
/
make_params.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
#include "ast_symbol.h"
#include "error.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
ast *find_ast_type(PclType tp) {
/*creates the corresponding ast structure of a type*/
switch (tp->kind) {
case TYPE_INTEGER: {
return ast_type(INT, -1, NULL);
}
case TYPE_REAL: {
return ast_type(REAL, -1, NULL);
}
case TYPE_BOOLEAN: {
return ast_type(BOOL, -1, NULL);
}
case TYPE_CHAR: {
return ast_type(CHAR, -1, NULL);
}
case TYPE_ARRAY: {
return ast_type(ARRAY, tp->size, find_ast_type(tp->refType));
}
case TYPE_IARRAY: {
return ast_type(IARRAY, 0, find_ast_type(tp->refType));
}
case TYPE_POINTER: {
return ast_type(ARRAY, -1, find_ast_type(tp->refType));
}
default: {
printf("Unknown error!\n");
return NULL;
}
}
}
int make_params(ast *t, SymbolEntry *cur_func) {
/*Scopes in PCL are similar to those of the Pascal programming language. Thus,
* local variables of procedures or functions can be visible in
* functions/procedures defined inside them. As the llvm didn't include a way
* to access the individual stack frames to get these variables from the
* previous activation records, this function alters the ast adding those
* variables as arguments (by reference) to the corresponding functions. Due
* to the support of recursion and mutual recursion in PCL, this is a fixed
* point computation.*/
SymbolEntry *p, *p1;
PclType tp;
PassMode pass_type;
ast *head, *head1;
int ret, ret2, ret3, flag;
if (!t) { // Should not be reached
error("Unknown Error");
return 1;
}
switch (t->k) {
case AND:
case OR:
case DIV:
case MOD:
case NEQ:
case EQ:
case GEQ:
case LEQ:
case LESS:
case GREATER:
case PLUS:
case MINUS:
case TIMES:
case DIVIDE:
case WHILE:
case INDEX:
case DISPOSE:
case BLOCK:
case BODY:
case IF:
case NEW:
case NOT:
case VAR:
case DEREF:
case REF:
case DISPOSE_ARRAY:
case VARREF:
case LOCAL_VAR:
case ASSIGN:
case STMT: {
/*All these nodes in the AST just have to pass the control below. The
* variables needed to be passed as arguments are located in the leaves of
* the AST*/
ret = (t->left && make_params(t->left, cur_func));
ret2 = (t->right && make_params(t->right, cur_func));
ret3 = (t->mid && make_params(t->mid, cur_func));
return ret || ret2 || ret3;
}
case IARRAY:
case ARRAY:
case BOOL:
case BOOL_CONST:
case CHAR:
case CHAR_CONST:
case INT:
case INT_CONST:
case REAL:
case REAL_CONST:
case RESULT:
case STR_CONST:
case LABEL:
case NIL:
case GOTO:
case POINTER: {
/*No leaves below those nodes contain the variables we are looking for*/
return 0;
}
case FORWARD:
if (make_params(t->left, cur_func))
return 1;
forwardFunction(t->left->sentry);
t->left->sentry->u.eFunction.forward_decl = t;
closeScope();
break;
case PROCEDURE:
case FUNCTION: {
/*These are the Header nodes. They just have to create the symbol entry of
* the function/procedure they represent at the symbol table*/
t->sentry = newFunction(t->id);
openScope();
if (t->left) { // t->left : seq_formal (parameters)
head = t->left; // seq_formal
while (head) {
tp = head->left->right->type;
pass_type = head->left->k == VARREF ? PASS_BY_REFERENCE : PASS_BY_VALUE;
head1 = head->left->left;
while (head1) {
newParameter(head1->id, tp, pass_type, t->sentry);
head1 = head1->right;
}
head = head->right;
}
}
endFunctionHeader(t->sentry, t->type);
return 0;
}
case PROGRAM: {
/*Initialize the first scope and define builtins*/
openScope();
define_builtins();
ret = make_params(t->left, NULL);
closeScope();
return ret;
}
case SEQ_EXPR:
case SEQ_FORMAL:
case SEQ_LOCAL:
case SEQ_LOCAL_VAR:
case SEQ_STMT: {
/*To avoid many recursive calls of this function, we iterate through the
* linked list that each of these nodes represent.*/
ret = 0;
head = t;
while (head) {
if (head->left && make_params(head->left, cur_func)) {
ret = 1;
}
head = head->right;
}
return ret;
}
case LOCAL_VAR_INSTANCE: {
/*Declare variables at the symbol table*/
tp = t->right->type;
head = t->left;
while (head) {
newVariable(head->id, tp);
head = head->right;
}
return 0;
}
case ID: {
/*If this identifier is not in the current scope, then it is needed as a by
* reference parameter in the current function. Also return that a change
* has took place so this function can run again until the AST is
* stabilized*/
ret = 0;
if (!lookupEntry(t->id, LOOKUP_CURRENT_SCOPE, false)) {
cur_func->u.eFunction.extra_params->insert(t->id);
ret = 1;
}
return ret;
}
case CALL: {
/*Run through the arguments for variables we need to add in the calling
* function as arguments. Add the extra parameters already found for the
* function/procedure called. If any of these things happen, return that a
* change has been made.*/
ret = 0;
if (t->left)
ret = make_params(t->left, cur_func);
p = lookupEntry(t->id, LOOKUP_ALL_SCOPES, false);
flag = 1;
for (p1 = p->u.eFunction.firstArgument; p1; p1 = p1->u.eParameter.next) {
if (flag) {
if (!t->left) {
char *id = (char *)malloc(strlen(p1->id) * sizeof(char));
strcpy(id, p1->id);
t->left = ast_seq_expr(ast_id(id), NULL);
ret = 1;
}
head = t->left;
flag = 0;
} else {
if (!head->right) {
char *id = (char *)malloc(strlen(p1->id) * sizeof(char));
strcpy(id, p1->id);
head->right = ast_seq_expr(ast_id(id), NULL);
ret = 1;
}
head = head->right;
}
}
if (t->left) {
for (head = t->left; head->right; head = head->right)
;
flag = 0;
} else
flag = 1;
for (auto it = p->u.eFunction.extra_params->begin();
it != p->u.eFunction.extra_params->end(); ++it) {
if (flag) {
t->left = ast_seq_expr(ast_id(const_cast<char *>((*it).c_str())), NULL);
head = t->left;
flag = 0;
ret = 1;
} else {
head->right =
ast_seq_expr(ast_id(const_cast<char *>((*it).c_str())), NULL);
head = head->right;
ret = 1;
}
if (!lookupEntry((*it).c_str(), LOOKUP_CURRENT_SCOPE, false)) {
cur_func->u.eFunction.extra_params->insert(*it);
ret = 1;
}
}
return ret;
}
case DEFINITION: {
/*create the symbol entry of the function/procedure defined and pass it
* below to gain the extra arguments. If any of them occur, add them to the
* function/procedure in which this is defined*/
make_params(t->left, cur_func);
ret = make_params(t->right, t->left->sentry);
closeScope();
if (ret) {
head = t->left; // header
if (head->left) { // arguments already exist
for (head = head->left; head->right; head = head->right)
;
flag = 0;
} else
flag = 1;
for (auto &value : (*t->left->sentry->u.eFunction
.extra_params)) { // iterate through extra params
if (!lookupEntry(const_cast<char *>(value.c_str()),
LOOKUP_CURRENT_SCOPE, false)) {
cur_func->u.eFunction.extra_params->insert(
value); // add them to the outside function/procedure
}
p = lookupEntry(const_cast<char *>(value.c_str()), LOOKUP_ALL_SCOPES,
false);
if (p->entryType == ENTRY_VARIABLE)
tp = p->u.eVariable.type;
else
tp = p->u.eParameter.type;
if (flag) {
head->left = ast_seq_formal(
ast_formal(VARREF,
ast_seq_id(const_cast<char *>(value.c_str()), NULL),
find_ast_type(tp)),
NULL);
head->left->left->right->type = tp;
head = head->left;
flag = 0;
} else {
head->right = ast_seq_formal(
ast_formal(VARREF,
ast_seq_id(const_cast<char *>(value.c_str()), NULL),
find_ast_type(tp)),
NULL);
head->right->left->right->type = tp;
head = head->right;
}
}
if (t->left->sentry->u.eFunction.forward_decl) {
t->left->sentry->u.eFunction.forward_decl->left = t->left;
}
}
return ret;
}
case SEQ_ID:
case RETURN:
break;
default:
break;
}
return 0;
}
int make_parameters(ast *t) {
initSymbolTable(256);
int ret = make_params(t, NULL);
destroySymbolTable();
return ret;
}