forked from vojone/IFJ21
-
Notifications
You must be signed in to change notification settings - Fork 0
/
generator.h
479 lines (366 loc) · 12.2 KB
/
generator.h
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
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
/******************************************************************************
* IFJ21
* generator.h
*
* Authors: Juraj Dědič (xdedic07), Tomáš Dvořák (xdvora3r)
* Purpose: Header file of code generator
*
* Last change: 8. 12. 2021
*****************************************************************************/
/**
* @file generator.h
* @brief Header file of code generator
*
* @authors Juraj Dědič (xdedic07), Tomáš Dvořák (xdvora3r)
*/
#ifndef GENERATOR_H
#define GENERATOR_H
#include <stdio.h>
#include <stdlib.h>
#include "dstack.h"
#include <stdbool.h>
#include <stdarg.h>
#include <errno.h>
#include <float.h>
#include "symtable.h"
#include "scanner.h"
#define MAX_CNT_LEN 32 /**< Maximum length of value in counter */
#define GEN_WARNING true
/*** Structures and functions for handling internal representation of code ***/
/**For example of usage @see gen_test.cpp**/
/**
* @brief Element of DLL that represents instruction of target code
*/
typedef struct instruction {
string_t content; /**< Content of given instruction */
struct instruction *next; /**< Next instruction */
struct instruction *prev; /**< Instruction before */
} instr_t;
DSTACK_DECL(instr_t *, instr)
/**
* @brief Double linked list that represents target program
* @warning Not all operations with DLL behaves same as in other implementations
*/
typedef struct program {
instr_t *first_instr; /**< First instruction of program (DLL) */
instr_t *last_instr; /**< Last instruction of program (DLL) */
size_t cycle_nest_lvl; //number of whiles we are currently in
instr_stack_t cycle_stack; //pointer to the while which is first in the current scope
} prog_t;
DSTACK_DECL(prog_t, prog)
/**
* @brief stores pair of function name and pointer to function which should be generated in order to use it in the target code
*/
typedef struct funtions_array {
char *name;
void (*function_ptr)();
} function_name_t;
/**
* @brief Creates new empty intruction
* @return Pointer to newly created instruction or null if an error occured
*/
instr_t *new_instruction();
/**
* @brief Sets content of instruction (uses dynamic string @see dstring.h)
* @return EXIT_SUCCESS, if everything was OK (otherwise INTERNAL_ERROR)
*/
int set_instruction(instr_t *instr, const char *const _Format, va_list args);
/**
* @brief Correctly frees all resources held by intruction
*/
void instr_dtor(instr_t *instr);
/**
* @brief Inits new program structure
* @param program Pointer to program that will be initialized
*/
void init_new_prog(prog_t *program);
/**
* @brief Frees all resources held by given program structure
* @note After calling it, program will have same state as it has after initialization
* @param program Pointer to program that will be deleted
*/
void program_dtor(prog_t *program);
/**
* @brief Returns pointer to last instruction of given program
* @note If program is empty, returns NULL
*/
instr_t *get_last(prog_t *program);
/**
* @brief Returns pointer to first instruction of given program
* @note If program is empty, returns NULL
*/
instr_t *get_first(prog_t *program);
/**
* @brief Returns pointer to right neighbour of given instruction (next instruction)
* @note If fiven instruction is last, it returns NULL
*/
instr_t *get_next(instr_t *instr);
/**
* @brief Returns last instruction of given program
* @note If fiven instruction is last, it returns NULL
*/
instr_t *get_prev(instr_t *instr);
/**
* @brief Appends new instruction to given program
* @note It's variadic function, so it can be used as standard printf
*/
void app_instr(prog_t *dst, const char *const _Format, ...);
/**
* @brief Appends program (instruction sequence) to another program
* @warning Appended program cannot be destroyed! (something can be double freed)
*/
void app_prog(prog_t *dst, prog_t *prog);
/**
* @brief Inserts new instruction after given instruction
* @note It's variadic function, so it can be used as standard printf
* @warning If given pointer to instruction in argument is NULL it does nothing
*/
void ins_after(prog_t *dst, instr_t *instr, const char *const _Format, ...);
/**
* @brief Inserts new instruction before given instruction
* @note It's variadic function, so it can be used as standard printf
* @warning If given pointer to instruction in argument is NULL it does nothing
*/
void ins_before(prog_t *dst, instr_t *instr, const char *const _Format, ...);
/**
* @brief Reverts instructions in given interval (including borders)
* @note Interval is given by to pointers to instructions, use
* get_next/get_prev to make reversion only inside this interval
* @warning If an error occured during the reversing, it does nothing
*/
void revert(prog_t *dst, instr_t *from, instr_t *to);
/**
* @brief Prints program to standard output and adds '\n' after every instruction
*/
void print_program(prog_t *source);
/*** End of internal repre. functions and structures ***/
/**
* @brief inicializes the code
*/
void generate_init(prog_t *dst);
/**
* @brief generates builtin functions if they are in symtab
*/
int generate_builtin(prog_t *dst, symtab_t *symtab);
/**
* *---------FUNCTIONS---------
*/
/**
* @brief generates the start of function definition
* @name function name
*/
void generate_start_function(prog_t *dst,const char * name);
/**
* @brief generates parameters of a function
* @note they are declared reversely because they're popped from stack
* @param param_names TYPE: tok_stack_t - the stack of tokens with parameter names
*/
void generate_parameters(prog_t *dst, void *sym_stack,symtab_t *symtab , void *param_names, scanner_t * scanner);
/**
* @brief generates one parameter
* @param name of the parameter
*/
void generate_parameter(prog_t *dst,const char * name);
/**
* @brief generates the code needed to end a function definition
*/
void generate_end_function(prog_t *dst,const char * name);
/**
*
*/
void generate_call_function(prog_t *dst,const char * name);
/**
* @brief pushes NILs to stack
* @param n how many NIL returns to push
*/
void generate_additional_returns(prog_t *dst,size_t n);
/**
* @brief generates return statement
*/
void generate_return(prog_t *dst);
/**
* @brief generates pops for eliminating redundant values on stack
*/
void generate_dump_values(prog_t *dst, size_t save_n, size_t delete_n);
/**
* @brief Picks n_values from stack in pushes it back in reversed order
*/
void generate_reverse_stack(prog_t *dst, size_t n_values);
/**
* *---------VARIABLES---------
*/
/**
* @brief declares a variable
* @param var_id identifier of the variable
* @note we will search the actual unique identifier in the symtab
*/
void generate_declare_variable( prog_t *dst,void *sym_stack,symtab_t *symtab , token_t *var_id, scanner_t * scanner);
/**
* @brief assigns variables from stack to variables
* @param param_names TYPE: tok_stack_t - the stack of tokens with variable names
*/
void generate_multiple_assignment(prog_t *dst, void *sym_stack,symtab_t *symtab , void *param_names, scanner_t * scanner);
/**
* @brief pops the value from top of stack into variable
* @param name name of the variable
*/
void generate_assign_value(prog_t *dst,const char * name);
/**
* @brief pushes a value (variable or static) to the stack
* @param name identifier or the actual value to push
* @note used in expression parsing
*/
void generate_value_push( prog_t *dst,sym_type_t type, sym_dtype_t dtype, const char * name );
/**
* *--------CONDIONS--------
*/
void generate_if_condition(prog_t *dst,size_t n);
void generate_if_end(prog_t *dst,size_t n);
void generate_else_end(prog_t *dst, size_t n);
/**
* *--------LOOPS--------
*/
void generate_while_condition_beginning(prog_t *dst,size_t n);
void generate_while_condition_evaluate(prog_t *dst,size_t n);
void generate_while_end(prog_t *dst,size_t n);
/**
* *---------OPERATIONS---------
*/
void generate_operation_add(prog_t *dst);
void generate_operation_sub(prog_t *dst);
void generate_operation_mul(prog_t *dst);
void generate_operation_div(prog_t *dst);
void generate_operation_div(prog_t *dst);
void generate_operation_idiv(prog_t *dst);
void generate_operation_unary_minus(prog_t *dst);
void generate_operation_eq(prog_t *dst);
void generate_operation_neq(prog_t *dst);
void generate_operation_gt(prog_t *dst);
void generate_operation_lt(prog_t *dst);
void generate_operation_gte(prog_t *dst);
void generate_operation_lte(prog_t *dst);
void generate_operation_concat(prog_t *dst);
void generate_operation_strlen(prog_t *dst);
void generate_operation_pow(prog_t *dst);
void generate_operation_function_pow(prog_t *dst);
void generate_operation_mod(prog_t *dst);
void generate_operation_function_mod(prog_t *dst);
/**
* *---------BUILTIN---------
*/
/**
* @brief generates prebuilt write function
* @note supports exactly one argument
*/
void generate_write_function(prog_t *dst);
/**
* @brief generates prebuilt reads function
*/
void generate_reads_function(prog_t *dst);
/**
* @brief generates prebuilt readi function
*/
void generate_readi_function(prog_t *dst);
/**
* @brief generates prebuilt readn function
*/
void generate_readn_function(prog_t *dst);
/**
* @brief generates prebuilt tointeger function
*/
void generate_tointeger_function(prog_t *dst);
/**
* @brief generates prebuilt chr function
*/
void generate_chr_function(prog_t *dst);
/**
* @brief generates prebuilt ord function
*/
void generate_ord_function(prog_t *dst);
/**
* @brief generates prebuilt substr function
*/
void generate_substr_function(prog_t *dst);
/**
* *BUILTIN INTERNAL FUNCTIONS - cannot be called from IFJ21 source code
*/
/**
* @brief checks the operand on top of the stack for 0
* @note if there is a zero it will exit exit with error 9
*/
void generate_checkzero_function_int(prog_t *dst);
/**
* @brief checks the operand on top of the stack for 0
* @note if there is a zero it will exit exit with error 9
*/
void generate_checkzero_function_float(prog_t *dst);
/**
* @brief checks one operand on top of the stack for nil
* @note if there is a nil it will exit exit with error 8
*/
void generate_checknil_function_single(prog_t *dst);
/**
* @brief checks two operands on top of the stack for nil
* @note if there is a nil it will exit exit with error 8
*/
void generate_checknil_function_double(prog_t *dst);
/**
* @brief function to get negative value on top of stack
*/
void generate_unaryminus_function(prog_t *dst);
/**
* @brief function to convert values on top of the stack to same types
* @note if there is float and int it will make 2 floats
*/
void generate_same_types(prog_t *dst);
/**
* @brief convert 2 values on top of the stack to floats
*/
void generate_force_floats(prog_t *dst);
/**
* @brief convert 2 values on top of the stack to ints
*/
void generate_force_ints(prog_t *dst);
/**
* @brief if there is not bool on top of stack it will convert the value to bool
*/
void generate_tobool(prog_t *dst_code);
/**
* @brief converts the value to number
*/
void generate_int2num(prog_t *dst_code);
/**
* *---------VARIOUS---------
*/
/**
* @brief Calls function to implicit recast of integer value on top of stack to number
*/
void impl_int2num(prog_t *dst_code);
void generate_clears(prog_t *dst_code);
/**
* *---------UTILITY---------
*/
/**
* @brief gets the unique identifier from symtable
* @param var_id the token which we're going to search
*/
string_t get_unique_name( void *sym_stack,symtab_t *symtab , token_t *var_id, scanner_t * scanner );
/**
* @brief printf the code
* @note ends each call witn \n
*/
void code_print(prog_t *dst, const char *const _Format, ...);
/**
* @brief converts dtype into format used in ifjcode21
* @param dtype input data type used in symtable
* @return string with type for code generation
*/
const char *convert_type(sym_dtype_t dtype);
/**
* @brief converts string from token format ie. "this is a string" to "this\032is\032string"
* @param str the input string
* @param out pointer to the output string
*/
void to_ascii(const char * str, string_t * out);
#endif
/*** End of generator.h ***/