LCOV - code coverage report
Current view: top level - MinimalCC - expression.c (source / functions) Hit Total Coverage
Test: test.info Lines: 0 1184 0.0 %
Date: 2022-06-06 21:08:49 Functions: 0 53 0.0 %
Branches: 0 769 0.0 %

           Branch data     Line data    Source code
       1                 :            : #include <stdlib.h>
       2                 :            : #include <stdio.h>
       3                 :            : #include <string.h>
       4                 :            : #include <stdarg.h>
       5                 :            : #include "dictionary.h"
       6                 :            : #include "expression.h"
       7                 :            : #include "compile.h"
       8                 :            : 
       9                 :            : int current_scope;
      10                 :            : 
      11                 :            : dictionary *local_variables[MAX_SCOPE];
      12                 :            : dictionary global_variables;
      13                 :            : unsigned int num_labels = 0;
      14                 :            : unsigned int current_string = 0;
      15                 :            : static unsigned int order_of_operations[] = {0, 9, 9, 10, 10, 1, 7, 7, 7, 7, 6, 6, 5, 4, 9, 3, 2, 8, 8};
      16                 :            : 
      17                 :            : unsigned char do_print;
      18                 :            : 
      19                 :            : //Wrapper to fprintf to control whether we actually write to a file
      20                 :          0 : void fileprint(FILE *fp, const char *format, ...){
      21                 :          0 :         va_list ap;
      22                 :            : 
      23         [ #  # ]:          0 :         if(do_print){
      24                 :          0 :                 va_start(ap, format);
      25                 :          0 :                 vfprintf(fp, format, ap);
      26                 :          0 :                 va_end(ap);
      27                 :            :         }
      28                 :          0 : }
      29                 :            : 
      30                 :          0 : void operation_none_func(char *reg_a, char *reg_b, value *value_a, value *value_b, FILE *output_file, type *output_type){
      31                 :          0 :         snprintf(error_message, sizeof(error_message), "Unrecognized operation");
      32                 :          0 :         do_error(1);
      33                 :          0 : }
      34                 :            : 
      35                 :          0 : void operation_add_func(char *reg_a, char *reg_b, value *value_a, value *value_b, FILE *output_file, type *output_type){
      36                 :          0 :         value *pointer_value;
      37                 :          0 :         char *integer_reg;
      38                 :          0 :         unsigned int pointer_size;
      39                 :            : 
      40   [ #  #  #  # ]:          0 :         if(peek_type(&(value_a->data_type)) == type_function || peek_type(&(value_b->data_type)) == type_function){
      41                 :          0 :                 snprintf(error_message, sizeof(error_message), "Addition of function type is undefined");
      42                 :          0 :                 do_error(1);
      43                 :            :         }
      44         [ #  # ]:          0 :         if(peek_type(&(value_a->data_type)) == type_pointer){
      45         [ #  # ]:          0 :                 if(peek_type(&(value_b->data_type)) == type_pointer){
      46                 :          0 :                         snprintf(warning_message, sizeof(warning_message), "Adding two pointers together. Treating them as integers instead");
      47                 :          0 :                         do_warning();
      48                 :          0 :                         fileprint(output_file, "add %s, %s, %s\n", reg_a, reg_a, reg_b);
      49                 :          0 :                         *output_type = value_a->data_type;
      50                 :          0 :                         return;
      51                 :            :                 }
      52                 :          0 :                 pointer_value = value_a;
      53                 :          0 :                 integer_reg = reg_b;
      54                 :            :         } else {
      55         [ #  # ]:          0 :                 if(peek_type(&(value_b->data_type)) == type_pointer){
      56                 :          0 :                         pointer_value = value_b;
      57                 :          0 :                         integer_reg = reg_a;
      58                 :            :                 } else {
      59                 :          0 :                         fileprint(output_file, "add %s, %s, %s\n", reg_a, reg_a, reg_b);
      60                 :          0 :                         *output_type = INT_TYPE;
      61                 :          0 :                         return;
      62                 :            :                 }
      63                 :            :         }
      64                 :          0 :         pointer_size = type_size(&(pointer_value->data_type), 1);
      65         [ #  # ]:          0 :         if(pointer_size == 4){
      66                 :          0 :                 fileprint(output_file, "sll %s, %s, 2\n", integer_reg, integer_reg);
      67         [ #  # ]:          0 :         } else if(pointer_size != 1){
      68                 :          0 :                 fileprint(output_file, "li $t2, %d\n", pointer_size);
      69                 :          0 :                 fileprint(output_file, "mult %s, $t2\n", integer_reg);
      70                 :          0 :                 fileprint(output_file, "mflo %s\n", integer_reg);
      71                 :            :         }
      72                 :          0 :         fileprint(output_file, "add %s, %s, %s\n", reg_a, reg_a, reg_b);
      73                 :            : 
      74                 :          0 :         *output_type = pointer_value->data_type;
      75                 :            : }
      76                 :            : 
      77                 :          0 : void operation_subtract_func(char *reg_a, char *reg_b, value *value_a, value *value_b, FILE *output_file, type *output_type){
      78                 :          0 :         type *pointer_type;
      79                 :          0 :         type *pointer_type2;
      80                 :          0 :         value *pointer_value;
      81                 :          0 :         char *integer_reg;
      82                 :          0 :         unsigned int pointer_size;
      83                 :            : 
      84   [ #  #  #  # ]:          0 :         if(peek_type(&(value_a->data_type)) == type_function || peek_type(&(value_b->data_type)) == type_function){
      85                 :          0 :                 snprintf(error_message, sizeof(error_message), "Subtraction of function type is undefined");
      86                 :          0 :                 do_error(1);
      87                 :            :         }
      88         [ #  # ]:          0 :         if(peek_type(&(value_a->data_type)) == type_pointer){
      89         [ #  # ]:          0 :                 if(peek_type(&(value_b->data_type)) == type_pointer){
      90                 :          0 :                         pointer_type = &(value_a->data_type);
      91                 :          0 :                         pointer_type2 = &(value_b->data_type);
      92         [ #  # ]:          0 :                         if(!types_equal(pointer_type, pointer_type2)){
      93                 :          0 :                                 snprintf(error_message, sizeof(error_message), "Cannot subtract pointers to different types");
      94                 :          0 :                                 do_error(1);
      95                 :            :                         }
      96                 :          0 :                         fileprint(output_file, "sub %s, %s, %s\n", reg_a, reg_a, reg_b);
      97         [ #  # ]:          0 :                         if(type_size(pointer_type, 1) == 4){
      98                 :          0 :                                 fileprint(output_file, "sra %s, %s, 2\n", reg_a, reg_a);
      99         [ #  # ]:          0 :                         } else if(type_size(pointer_type, 1) != 1){
     100                 :          0 :                                 fileprint(output_file, "li $t2, %d\n", type_size(pointer_type, 1));
     101                 :          0 :                                 fileprint(output_file, "div %s, $t2\n", reg_a);
     102                 :          0 :                                 fileprint(output_file, "mflo %s\n", reg_a);
     103                 :            :                         }
     104                 :          0 :                         *output_type = INT_TYPE;
     105                 :          0 :                         return;
     106                 :            :                 }
     107                 :          0 :                 pointer_value = value_a;
     108                 :          0 :                 integer_reg = reg_b;
     109                 :            :         } else {
     110         [ #  # ]:          0 :                 if(peek_type(&(value_b->data_type)) == type_pointer){
     111                 :          0 :                         pointer_value = value_b;
     112                 :          0 :                         integer_reg = reg_a;
     113                 :            :                 } else {
     114                 :          0 :                         fileprint(output_file, "sub %s, %s, %s\n", reg_a, reg_a, reg_b);
     115                 :          0 :                         *output_type = INT_TYPE;
     116                 :          0 :                         return;
     117                 :            :                 }
     118                 :            :         }
     119                 :          0 :         pointer_size = type_size(&(pointer_value->data_type), 1);
     120         [ #  # ]:          0 :         if(pointer_size == 4){
     121                 :          0 :                 fileprint(output_file, "sll %s, %s, 2\n", integer_reg, integer_reg);
     122         [ #  # ]:          0 :         } else if(pointer_size != 1){
     123                 :          0 :                 fileprint(output_file, "li $t2, %d\n", pointer_size);
     124                 :          0 :                 fileprint(output_file, "mult %s, $t2\n", integer_reg);
     125                 :          0 :                 fileprint(output_file, "mflo %s\n", integer_reg);
     126                 :            :         }
     127                 :          0 :         fileprint(output_file, "sub %s, %s, %s\n", reg_a, reg_a, reg_b);
     128                 :            : 
     129                 :          0 :         *output_type = pointer_value->data_type;
     130                 :            : }
     131                 :            : 
     132                 :          0 : void operation_multiply_func(char *reg_a, char *reg_b, value *value_a, value *value_b, FILE *output_file, type *output_type){
     133   [ #  #  #  #  :          0 :         if((!types_equal(&(value_a->data_type), &INT_TYPE) && !types_equal(&(value_a->data_type), &CHAR_TYPE)) || (!types_equal(&(value_b->data_type), &INT_TYPE) && !types_equal(&(value_b->data_type), &CHAR_TYPE))){
             #  #  #  # ]
     134                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot multiply non-int types");
     135                 :          0 :                 do_error(1);
     136                 :            :         }
     137                 :          0 :         fileprint(output_file, "mult %s, %s\n", reg_a, reg_b);
     138                 :          0 :         fileprint(output_file, "mflo %s\n", reg_a);
     139                 :          0 :         *output_type = INT_TYPE;
     140                 :          0 : }
     141                 :            : 
     142                 :          0 : void operation_divide_func(char *reg_a, char *reg_b, value *value_a, value *value_b, FILE *output_file, type *output_type){
     143   [ #  #  #  #  :          0 :         if((!types_equal(&(value_a->data_type), &INT_TYPE) && !types_equal(&(value_a->data_type), &CHAR_TYPE)) || (!types_equal(&(value_b->data_type), &INT_TYPE) && !types_equal(&(value_b->data_type), &CHAR_TYPE))){
             #  #  #  # ]
     144                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot divide non-int types");
     145                 :          0 :                 do_error(1);
     146                 :            :         }
     147                 :          0 :         fileprint(output_file, "div %s, %s\n", reg_a, reg_b);
     148                 :          0 :         fileprint(output_file, "mflo %s\n", reg_a);
     149                 :          0 :         *output_type = INT_TYPE;
     150                 :          0 : }
     151                 :            : 
     152                 :          0 : void operation_modulo_func(char *reg_a, char *reg_b, value *value_a, value *value_b, FILE *output_file, type *output_type){
     153   [ #  #  #  #  :          0 :         if((!types_equal(&(value_a->data_type), &INT_TYPE) && !types_equal(&(value_a->data_type), &CHAR_TYPE)) || (!types_equal(&(value_b->data_type), &INT_TYPE) && !types_equal(&(value_b->data_type), &CHAR_TYPE))){
             #  #  #  # ]
     154                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot modulo non-int types");
     155                 :          0 :                 do_error(1);
     156                 :            :         }
     157                 :          0 :         fileprint(output_file, "div %s, %s\n", reg_a, reg_b);
     158                 :          0 :         fileprint(output_file, "mfhi %s\n", reg_a);
     159                 :          0 :         *output_type = INT_TYPE;
     160                 :          0 : }
     161                 :            : 
     162                 :          0 : void operation_assign_func(char *reg_a, char *reg_b, value *value_a, value *value_b, FILE *output_file, type *output_type){
     163         [ #  # ]:          0 :         if(!value_a->is_reference){
     164                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot assign to r-value");
     165                 :          0 :                 do_error(1);
     166                 :            :         }
     167                 :          0 :         pop_type(&(value_a->data_type));
     168         [ #  # ]:          0 :         if(peek_type(&(value_a->data_type)) == type_function){
     169                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot assign to function");
     170                 :          0 :                 do_error(1);
     171                 :            :         }
     172         [ #  # ]:          0 :         if(type_size(&(value_a->data_type), 0) == 4){
     173                 :          0 :                 fileprint(output_file, "sw %s, 0(%s)\n", reg_b, reg_a);
     174         [ #  # ]:          0 :         } else if(type_size(&(value_a->data_type), 0) == 1){
     175                 :          0 :                 fileprint(output_file, "sb %s, 0(%s)\n", reg_b, reg_a);
     176                 :            :         }
     177                 :          0 :         fileprint(output_file, "move %s, %s\n", reg_a, reg_b);
     178                 :          0 :         *output_type = value_b->data_type;
     179                 :          0 : }
     180                 :            : 
     181                 :          0 : void operation_less_than_func(char *reg_a, char *reg_b, value *value_a, value *value_b, FILE *output_file, type *output_type){
     182   [ #  #  #  #  :          0 :         if((!types_equal(&(value_a->data_type), &INT_TYPE) && !types_equal(&(value_a->data_type), &CHAR_TYPE)) || (!types_equal(&(value_b->data_type), &INT_TYPE) && !types_equal(&(value_b->data_type), &CHAR_TYPE))){
             #  #  #  # ]
     183                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot compare non-int types with '<'");
     184                 :          0 :                 do_error(1);
     185                 :            :         }
     186                 :          0 :         fileprint(output_file, "slt %s, %s, %s\n", reg_a, reg_a, reg_b);
     187                 :          0 :         *output_type = INT_TYPE;
     188                 :          0 : }
     189                 :            : 
     190                 :          0 : void operation_greater_than_func(char *reg_a, char *reg_b, value *value_a, value *value_b, FILE *output_file, type *output_type){
     191   [ #  #  #  #  :          0 :         if((!types_equal(&(value_a->data_type), &INT_TYPE) && !types_equal(&(value_a->data_type), &CHAR_TYPE)) || (!types_equal(&(value_b->data_type), &INT_TYPE) && !types_equal(&(value_b->data_type), &CHAR_TYPE))){
             #  #  #  # ]
     192                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot compare non-int types with '>'");
     193                 :          0 :                 do_error(1);
     194                 :            :         }
     195                 :          0 :         fileprint(output_file, "sgt %s, %s, %s\n", reg_a, reg_a, reg_b);
     196                 :          0 :         *output_type = INT_TYPE;
     197                 :          0 : }
     198                 :            : 
     199                 :          0 : void operation_less_than_or_equal_func(char *reg_a, char *reg_b, value *value_a, value *value_b, FILE *output_file, type *output_type){
     200   [ #  #  #  #  :          0 :         if((!types_equal(&(value_a->data_type), &INT_TYPE) && !types_equal(&(value_a->data_type), &CHAR_TYPE)) || (!types_equal(&(value_b->data_type), &INT_TYPE) && !types_equal(&(value_b->data_type), &CHAR_TYPE))){
             #  #  #  # ]
     201                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot compare non-int types with '<='");
     202                 :          0 :                 do_error(1);
     203                 :            :         }
     204                 :          0 :         fileprint(output_file, "sgt %s, %s, %s\n", reg_a, reg_a, reg_b);
     205                 :          0 :         fileprint(output_file, "seq %s, %s, $zero\n", reg_a, reg_a);
     206                 :          0 :         *output_type = INT_TYPE;
     207                 :          0 : }
     208                 :            : 
     209                 :          0 : void operation_greater_than_or_equal_func(char *reg_a, char *reg_b, value *value_a, value *value_b, FILE *output_file, type *output_type){
     210   [ #  #  #  #  :          0 :         if((!types_equal(&(value_a->data_type), &INT_TYPE) && !types_equal(&(value_a->data_type), &CHAR_TYPE)) || (!types_equal(&(value_b->data_type), &INT_TYPE) && !types_equal(&(value_b->data_type), &CHAR_TYPE))){
             #  #  #  # ]
     211                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot compare non-int types with '>='");
     212                 :          0 :                 do_error(1);
     213                 :            :         }
     214                 :          0 :         fileprint(output_file, "slt %s, %s, %s\n", reg_a, reg_a, reg_b);
     215                 :          0 :         fileprint(output_file, "seq %s, %s, $zero\n", reg_a, reg_a);
     216                 :          0 :         *output_type = INT_TYPE;
     217                 :          0 : }
     218                 :            : 
     219                 :          0 : void operation_equals_func(char *reg_a, char *reg_b, value *value_a, value *value_b, FILE *output_file, type *output_type){
     220   [ #  #  #  # ]:          0 :         if(peek_type(&(value_a->data_type)) == type_function || peek_type(&(value_b->data_type)) == type_function){
     221                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot compare function types");
     222                 :          0 :                 do_error(1);
     223                 :            :         }
     224         [ #  # ]:          0 :         if(peek_type(&(value_a->data_type)) == type_pointer){
     225         [ #  # ]:          0 :                 if(peek_type(&(value_b->data_type)) == type_pointer){
     226                 :          0 :                         pop_type(&(value_a->data_type));
     227                 :          0 :                         pop_type(&(value_b->data_type));
     228         [ #  # ]:          0 :                         if(!types_equal(&(value_a->data_type), &(value_b->data_type))){
     229                 :          0 :                                 snprintf(warning_message, sizeof(warning_message), "Comparing incompatible data types");
     230                 :          0 :                                 do_warning();
     231                 :            :                         }
     232                 :          0 :                         fileprint(output_file, "seq %s, %s, %s\n", reg_a, reg_a, reg_b);
     233                 :          0 :                         *output_type = INT_TYPE;
     234                 :            :                 } else {
     235                 :          0 :                         snprintf(warning_message, sizeof(warning_message), "Comparing pointer and non-pointer types");
     236                 :          0 :                         do_warning();
     237                 :          0 :                         fileprint(output_file, "seq %s, %s, %s\n", reg_a, reg_a, reg_b);
     238                 :          0 :                         *output_type = INT_TYPE;
     239                 :            :                 }
     240                 :            :         } else {
     241         [ #  # ]:          0 :                 if(peek_type(&(value_b->data_type)) == type_pointer){
     242                 :          0 :                         snprintf(warning_message, sizeof(warning_message), "Comparing pointer and non-pointer types");
     243                 :          0 :                         do_warning();
     244                 :            :                 }
     245                 :          0 :                 fileprint(output_file, "seq %s, %s, %s\n", reg_a, reg_a, reg_b);
     246                 :          0 :                 *output_type = INT_TYPE;
     247                 :            :         }
     248                 :          0 : }
     249                 :            : 
     250                 :          0 : void operation_not_equals_func(char *reg_a, char *reg_b, value *value_a, value *value_b, FILE *output_file, type *output_type){
     251   [ #  #  #  # ]:          0 :         if(peek_type(&(value_a->data_type)) == type_function || peek_type(&(value_b->data_type)) == type_function){
     252                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot compare function types");
     253                 :          0 :                 do_error(1);
     254                 :            :         }
     255         [ #  # ]:          0 :         if(peek_type(&(value_a->data_type)) == type_pointer){
     256         [ #  # ]:          0 :                 if(peek_type(&(value_b->data_type)) == type_pointer){
     257                 :          0 :                         pop_type(&(value_a->data_type));
     258                 :          0 :                         pop_type(&(value_b->data_type));
     259         [ #  # ]:          0 :                         if(!types_equal(&(value_a->data_type), &(value_b->data_type))){
     260                 :          0 :                                 snprintf(warning_message, sizeof(warning_message), "Comparing incompatible data types");
     261                 :          0 :                                 do_warning();
     262                 :            :                         }
     263                 :          0 :                         fileprint(output_file, "sne %s, %s, %s\n", reg_a, reg_a, reg_b);
     264                 :          0 :                         *output_type = INT_TYPE;
     265                 :            :                 } else {
     266                 :          0 :                         snprintf(warning_message, sizeof(warning_message), "Comparing pointer and non-pointer types");
     267                 :          0 :                         do_warning();
     268                 :          0 :                         fileprint(output_file, "sne %s, %s, %s\n", reg_a, reg_a, reg_b);
     269                 :          0 :                         *output_type = INT_TYPE;
     270                 :            :                 }
     271                 :            :         } else {
     272         [ #  # ]:          0 :                 if(peek_type(&(value_b->data_type)) == type_pointer){
     273                 :          0 :                         snprintf(warning_message, sizeof(warning_message), "Comparing pointer and non-pointer types");
     274                 :          0 :                         do_warning();
     275                 :            :                 }
     276                 :          0 :                 fileprint(output_file, "sne %s, %s, %s\n", reg_a, reg_a, reg_b);
     277                 :          0 :                 *output_type = INT_TYPE;
     278                 :            :         }
     279                 :          0 : }
     280                 :            : 
     281                 :          0 : void operation_and_func(char *reg_a, char *reg_b, value *value_a, value *value_b, FILE *output_file, type *output_type){
     282   [ #  #  #  #  :          0 :         if((!types_equal(&(value_a->data_type), &INT_TYPE) && !types_equal(&(value_a->data_type), &CHAR_TYPE)) || (!types_equal(&(value_b->data_type), &INT_TYPE) && !types_equal(&(value_b->data_type), &CHAR_TYPE))){
             #  #  #  # ]
     283                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot '&' non-int types");
     284                 :          0 :                 do_error(1);
     285                 :            :         }
     286                 :          0 :         fileprint(output_file, "and %s, %s, %s\n", reg_a, reg_a, reg_b);
     287                 :          0 :         *output_type = INT_TYPE;
     288                 :          0 : }
     289                 :            : 
     290                 :          0 : void operation_or_func(char *reg_a, char *reg_b, value *value_a, value *value_b, FILE *output_file, type *output_type){
     291   [ #  #  #  #  :          0 :         if((!types_equal(&(value_a->data_type), &INT_TYPE) && !types_equal(&(value_a->data_type), &CHAR_TYPE)) || (!types_equal(&(value_b->data_type), &INT_TYPE) && !types_equal(&(value_b->data_type), &CHAR_TYPE))){
             #  #  #  # ]
     292                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot '|' non-int types");
     293                 :          0 :                 do_error(1);
     294                 :            :         }
     295                 :          0 :         fileprint(output_file, "or %s, %s, %s\n", reg_a, reg_a, reg_b);
     296                 :          0 :         *output_type = INT_TYPE;
     297                 :          0 : }
     298                 :            : 
     299                 :          0 : void operation_shift_left_func(char *reg_a, char *reg_b, value *value_a, value *value_b, FILE *output_file, type *output_type){
     300   [ #  #  #  #  :          0 :         if((!types_equal(&(value_a->data_type), &INT_TYPE) && !types_equal(&(value_a->data_type), &CHAR_TYPE)) || (!types_equal(&(value_b->data_type), &INT_TYPE) && !types_equal(&(value_b->data_type), &CHAR_TYPE))){
             #  #  #  # ]
     301                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot '<<' non-arithmetic types");
     302                 :          0 :                 do_error(1);
     303                 :            :         }
     304                 :          0 :         fileprint(output_file, "sllv %s, %s, %s\n", reg_a, reg_a, reg_b);
     305                 :          0 :         *output_type = INT_TYPE;
     306                 :          0 : }
     307                 :            : 
     308                 :          0 : void operation_shift_right_func(char *reg_a, char *reg_b, value *value_a, value *value_b, FILE *output_file, type *output_type){
     309   [ #  #  #  #  :          0 :         if((!types_equal(&(value_a->data_type), &INT_TYPE) && !types_equal(&(value_a->data_type), &CHAR_TYPE)) || (!types_equal(&(value_b->data_type), &INT_TYPE) && !types_equal(&(value_b->data_type), &CHAR_TYPE))){
             #  #  #  # ]
     310                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot '>>' non-arithmetic types");
     311                 :          0 :                 do_error(1);
     312                 :            :         }
     313                 :          0 :         fileprint(output_file, "srav %s, %s, %s\n", reg_a, reg_a, reg_b);
     314                 :          0 :         *output_type = INT_TYPE;
     315                 :          0 : }
     316                 :            : 
     317                 :            : void (*operation_functions[])(char *, char *, value *, value *, FILE *, type *) = {operation_none_func, operation_add_func, operation_subtract_func, operation_multiply_func, operation_divide_func, operation_assign_func, operation_less_than_func, operation_greater_than_func, operation_less_than_or_equal_func, operation_greater_than_or_equal_func, operation_equals_func, operation_not_equals_func, operation_and_func, operation_or_func, operation_modulo_func, operation_none_func, operation_none_func, operation_shift_left_func, operation_shift_right_func};
     318                 :            : 
     319                 :          0 : int type_size(type *t, unsigned int start_entry){
     320                 :          0 :         uint64_t d0;
     321                 :          0 :         uint64_t d1;
     322                 :          0 :         uint64_t d2;
     323                 :          0 :         unsigned int index;
     324                 :          0 :         unsigned int current_entry = 0;
     325                 :          0 :         int entry;
     326                 :          0 :         int output = 1;
     327                 :            : 
     328                 :          0 :         d0 = t->d0;
     329                 :          0 :         d1 = t->d1;
     330                 :          0 :         d2 = t->d2;
     331                 :          0 :         index = t->current_index;
     332                 :          0 :         while(1){
     333                 :          0 :                 entry = 0;
     334         [ #  # ]:          0 :                 if(d0&1){
     335                 :          0 :                         entry |= 1;
     336                 :            :                 }
     337         [ #  # ]:          0 :                 if(d1&1){
     338                 :          0 :                         entry |= 2;
     339                 :            :                 }
     340         [ #  # ]:          0 :                 if(d2&1){
     341                 :          0 :                         entry |= 4;
     342                 :            :                 }
     343         [ #  # ]:          0 :                 if(current_entry >= start_entry){
     344   [ #  #  #  #  :          0 :                         switch(entry){
                #  #  # ]
     345                 :          0 :                                 case type_void:
     346                 :          0 :                                         return output*VOID_SIZE;
     347                 :          0 :                                 case type_int:
     348                 :          0 :                                         return output*INT_SIZE;
     349                 :          0 :                                 case type_char:
     350                 :          0 :                                         return output*CHAR_SIZE;
     351                 :          0 :                                 case type_pointer:
     352                 :          0 :                                         return output*POINTER_SIZE;
     353                 :          0 :                                 case type_function:
     354                 :          0 :                                         return output*POINTER_SIZE;
     355                 :          0 :                                 case type_list:
     356                 :          0 :                                         index--;
     357                 :          0 :                                         output *= t->list_indicies[index];
     358                 :          0 :                                         break;
     359                 :          0 :                                 default:
     360                 :          0 :                                         return 0;
     361                 :            :                         }
     362         [ #  # ]:          0 :                 } else if(entry == type_list){
     363                 :          0 :                         index--;
     364                 :            :                 }
     365                 :          0 :                 d0 >>= 1;
     366                 :          0 :                 d1 >>= 1;
     367                 :          0 :                 d2 >>= 1;
     368                 :          0 :                 current_entry++;
     369                 :            :         }
     370                 :            : }
     371                 :            : 
     372                 :          0 : static void free_var(void *v){
     373                 :          0 :         variable *var;
     374                 :            : 
     375                 :          0 :         var = (variable *) v;
     376                 :          0 :         free(var->varname);
     377                 :          0 :         free(var);
     378                 :          0 : }
     379                 :            : 
     380                 :          0 : void free_global_variables(){
     381                 :          0 :         free_dictionary(global_variables, free_var);
     382                 :          0 : }
     383                 :            : 
     384                 :          0 : void free_local_variables(){
     385                 :          0 :         int i;
     386                 :            : 
     387         [ #  # ]:          0 :         for(i = current_scope; i >= 0; i--){
     388         [ #  # ]:          0 :                 if(local_variables[i]){
     389                 :          0 :                         free_dictionary(*local_variables[i], free_var);
     390                 :          0 :                         free(local_variables[i]);
     391                 :          0 :                         local_variables[i] = NULL;
     392                 :            :                 }
     393                 :            :         }
     394                 :            : 
     395                 :          0 :         variables_size = 0;
     396                 :          0 : }
     397                 :            : 
     398                 :          0 : static int var_stack_position(variable *var){
     399                 :          0 :         return saved_stack_size + variables_size - var->stack_pos - 4;
     400                 :            : }
     401                 :            : 
     402                 :          0 : unsigned int align4(unsigned int size){
     403                 :          0 :         unsigned int remainder;
     404                 :            : 
     405                 :          0 :         remainder = size%4;
     406         [ #  # ]:          0 :         if(remainder){
     407                 :          0 :                 size += 4 - remainder;
     408                 :            :         }
     409                 :            : 
     410                 :          0 :         return size;
     411                 :            : }
     412                 :            : 
     413                 :          0 : void compile_variable_initializer(char **c){
     414                 :          0 :         variable *var;
     415                 :          0 :         char varname_buf[32];
     416                 :          0 :         type vartype;
     417                 :            : 
     418                 :          0 :         vartype = EMPTY_TYPE;
     419                 :          0 :         parse_type(&vartype, c, varname_buf, NULL, 32, 0);
     420                 :          0 :         var = malloc(sizeof(variable));
     421                 :          0 :         var->varname = malloc(sizeof(char)*32);
     422                 :          0 :         var->var_type = vartype;
     423                 :          0 :         strcpy(var->varname, varname_buf);
     424         [ #  # ]:          0 :         variables_size += align4(type_size(&(var->var_type), 0));
     425                 :          0 :         var->stack_pos = variables_size - 4;
     426         [ #  # ]:          0 :         if(read_dictionary(*local_variables[current_scope], var->varname, 0)){
     427                 :          0 :                 free(var->varname);
     428                 :          0 :                 free(var);
     429                 :          0 :                 snprintf(error_message, sizeof(error_message), "Duplicate local variable definition");
     430                 :          0 :                 do_error(1);
     431                 :            :         }
     432                 :          0 :         write_dictionary(local_variables[current_scope], var->varname, var, 0);
     433                 :          0 :         skip_whitespace(c);
     434         [ #  # ]:          0 :         if(**c != ';'){
     435                 :          0 :                 snprintf(error_message, sizeof(error_message), "Expected ';'");
     436                 :          0 :                 do_error(1);
     437                 :            :         }
     438                 :          0 :         ++*c;
     439                 :          0 : }
     440                 :            : 
     441                 :          0 : void compile_integer(value *output, char **c, unsigned char dereference, unsigned char force_stack, FILE *output_file){
     442                 :          0 :         int int_value;
     443                 :            : 
     444                 :          0 :         output->data = allocate(force_stack);
     445                 :          0 :         int_value = strtol(*c, c, 0);
     446         [ #  # ]:          0 :         if(output->data.type == data_register){
     447                 :          0 :                 fileprint(output_file, "li $s%d, %d\n", output->data.reg, int_value);
     448         [ #  # ]:          0 :         } else if(output->data.type == data_stack){
     449                 :          0 :                 fileprint(output_file, "li $t0, %d\nsw $t0, %d($sp)\n", int_value, get_stack_pos(output->data));
     450                 :            :         }
     451                 :          0 :         output->data_type = INT_TYPE;
     452                 :          0 :         output->is_reference = 0;
     453                 :          0 : }
     454                 :            : 
     455                 :          0 : static void compile_local_variable(value *output, variable *var, unsigned char dereference, unsigned char force_stack, FILE *output_file){
     456                 :          0 :         data_entry data;
     457                 :          0 :         type data_type;
     458                 :            : 
     459                 :          0 :         data_type = var->var_type;
     460                 :          0 :         data = allocate(force_stack);
     461                 :          0 :         output->data_type = data_type;
     462                 :          0 :         output->data = data;
     463         [ #  # ]:          0 :         if(dereference){
     464         [ #  # ]:          0 :                 if(peek_type(&(var->var_type)) == type_list){
     465         [ #  # ]:          0 :                         if(data.type == data_register){
     466                 :          0 :                                 fileprint(output_file, "addi $s%d, $sp, %d\n", data.reg, var_stack_position(var));
     467         [ #  # ]:          0 :                         } else if(data.type == data_stack){
     468                 :          0 :                                 fileprint(output_file, "addi $t0, $sp, %d\n", var_stack_position(var));
     469                 :          0 :                                 fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(data));
     470                 :            :                         }
     471                 :          0 :                         pop_type(&(output->data_type));
     472                 :          0 :                         output->data_type.current_index--;
     473                 :          0 :                         add_type_entry(&(output->data_type), type_pointer);
     474                 :            :                 } else {
     475         [ #  # ]:          0 :                         if(data.type == data_register){
     476      [ #  #  # ]:          0 :                                 switch(type_size(&data_type, 0)){
     477                 :          0 :                                         case 1:
     478                 :          0 :                                                 fileprint(output_file, "lb $s%d, %d($sp)\n", data.reg, var_stack_position(var));
     479                 :          0 :                                                 break;
     480                 :          0 :                                         case 4:
     481                 :          0 :                                                 fileprint(output_file, "lw $s%d, %d($sp)\n", data.reg, var_stack_position(var));
     482                 :          0 :                                                 break;
     483                 :            : 
     484                 :            :                                 }
     485         [ #  # ]:          0 :                         } else if(data.type == data_stack){
     486      [ #  #  # ]:          0 :                                 switch(type_size(&data_type, 0)){
     487                 :          0 :                                         case 1:
     488                 :          0 :                                                 fileprint(output_file, "lb $t0, %d($sp)\n", var_stack_position(var));
     489                 :          0 :                                                 fileprint(output_file, "sb $t0, %d($sp)\n", get_stack_pos(data));
     490                 :          0 :                                                 break;
     491                 :          0 :                                         case 4:
     492                 :          0 :                                                 fileprint(output_file, "lw $t0, %d($sp)\n", var_stack_position(var));
     493                 :          0 :                                                 fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(data));
     494                 :          0 :                                                 break;
     495                 :            :                                 }
     496                 :          0 :                         }
     497                 :            :                 }
     498                 :            :         } else {
     499         [ #  # ]:          0 :                 if(peek_type(&(var->var_type)) == type_list){
     500         [ #  # ]:          0 :                         if(data.type == data_register){
     501                 :          0 :                                 fileprint(output_file, "addi $s%d, $sp, %d\n", data.reg, var_stack_position(var));
     502         [ #  # ]:          0 :                         } else if(data.type == data_stack){
     503                 :          0 :                                 fileprint(output_file, "addi $t0, $sp, %d\n", var_stack_position(var));
     504                 :          0 :                                 fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(data));
     505                 :            :                         }
     506                 :            :                 } else {
     507         [ #  # ]:          0 :                         if(data.type == data_register){
     508                 :          0 :                                 fileprint(output_file, "addi $s%d, $sp, %d\n", data.reg, var_stack_position(var));
     509         [ #  # ]:          0 :                         } else if(data.type == data_stack){
     510                 :          0 :                                 fileprint(output_file, "addi $t0, $sp, %d\n", var_stack_position(var));
     511                 :          0 :                                 fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(data));
     512                 :            :                         }
     513                 :            :                 }
     514                 :          0 :                 add_type_entry(&(output->data_type), type_pointer);
     515                 :            :         }
     516                 :            : 
     517                 :          0 :         output->is_reference = !dereference;
     518                 :          0 : }
     519                 :            : 
     520                 :          0 : static void compile_global_variable(value *output, variable *var, unsigned char dereference, unsigned char force_stack, FILE *output_file){
     521                 :          0 :         data_entry data;
     522                 :          0 :         type data_type;
     523                 :            : 
     524                 :          0 :         data_type = var->var_type;
     525                 :          0 :         data = allocate(force_stack);
     526         [ #  # ]:          0 :         if(data.type == data_register){
     527                 :          0 :                 fileprint(output_file, "la $s%d, %s\n", data.reg, var->varname);
     528                 :            :         } else {
     529                 :          0 :                 fileprint(output_file, "la $t0, %s\n", var->varname);
     530                 :            :         }
     531                 :          0 :         output->data = data;
     532                 :          0 :         output->is_reference = !dereference;
     533   [ #  #  #  # ]:          0 :         if(dereference && !var->leave_as_address){
     534         [ #  # ]:          0 :                 if(peek_type(&data_type) == type_list){
     535                 :          0 :                         pop_type(&data_type);
     536                 :          0 :                         data_type.current_index--;
     537                 :          0 :                         add_type_entry(&data_type, type_pointer);
     538         [ #  # ]:          0 :                         if(data.type == data_stack){
     539                 :          0 :                                 fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(data));
     540                 :            :                         }
     541                 :            :                 } else {
     542         [ #  # ]:          0 :                         if(data.type == data_register){
     543                 :          0 :                                 fileprint(output_file, "lw $s%d, 0($s%d)\n", data.reg, data.reg);
     544         [ #  # ]:          0 :                         } else if(data.type == data_stack){
     545                 :          0 :                                 fileprint(output_file, "lw $t0, 0($t0)\n");
     546                 :          0 :                                 fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(data));
     547                 :            :                         }
     548                 :            :                 }
     549                 :            :         } else {
     550                 :          0 :                 add_type_entry(&data_type, type_pointer);
     551         [ #  # ]:          0 :                 if(data.type == data_stack){
     552                 :          0 :                         fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(data));
     553                 :            :                 }
     554                 :            :         }
     555                 :          0 :         output->data_type = data_type;
     556                 :          0 : }
     557                 :            : 
     558                 :          0 : void compile_variable(value *output, char **c, unsigned char dereference, unsigned char force_stack, FILE *output_file){
     559                 :          0 :         char *start;
     560                 :          0 :         char varname[32] = {0};
     561                 :          0 :         unsigned int varname_length = 0;
     562                 :          0 :         variable *var;
     563                 :          0 :         int i;
     564                 :            : 
     565                 :          0 :         skip_whitespace(c);
     566                 :          0 :         start = *c;
     567   [ #  #  #  # ]:          0 :         while(alphanumeric(**c) && varname_length < 31){
     568                 :          0 :                 ++*c;
     569                 :          0 :                 varname_length++;
     570                 :            :         }
     571                 :          0 :         memcpy(varname, start, varname_length);
     572                 :          0 :         varname[31] = '\0';
     573                 :            : 
     574         [ #  # ]:          0 :         for(i = current_scope; i >= 0; i--){
     575                 :          0 :                 var = read_dictionary(*local_variables[i], varname, 0);
     576         [ #  # ]:          0 :                 if(var){
     577                 :          0 :                         break;
     578                 :            :                 }
     579                 :            :         }
     580                 :            : 
     581         [ #  # ]:          0 :         if(!var){
     582                 :          0 :                 var = read_dictionary(global_variables, varname, 0);
     583         [ #  # ]:          0 :                 if(!var){
     584                 :          0 :                         snprintf(error_message, sizeof(error_message), "Unrecognized variable '%s'", varname);
     585                 :          0 :                         do_error(1);
     586                 :            :                 }
     587                 :          0 :                 compile_global_variable(output, var, dereference, force_stack, output_file);
     588                 :            :         } else {
     589                 :          0 :                 compile_local_variable(output, var, dereference, force_stack, output_file);
     590                 :            :         }
     591                 :          0 : }
     592                 :            : 
     593                 :            : void compile_expression(value *output, char **c, unsigned char dereference, unsigned char force_stack, FILE *output_file);
     594                 :            : 
     595                 :          0 : void cast(value *v, type t, unsigned char do_warn, FILE *output_file){
     596                 :          0 :         type t_copy;
     597                 :          0 :         type_entry entry1;
     598                 :          0 :         type_entry entry2;
     599                 :            : 
     600   [ #  #  #  # ]:          0 :         if(types_equal(&(v->data_type), &VOID_TYPE) && !types_equal(&t, &VOID_TYPE)){
     601                 :          0 :                 snprintf(error_message, sizeof(error_message), "Can't cast void type to non-void type");
     602                 :          0 :                 do_error(1);
     603                 :            :         }
     604                 :            : 
     605         [ #  # ]:          0 :         if(peek_type(&t) == type_list){
     606                 :          0 :                 snprintf(error_message, sizeof(error_message), "Can't cast to an array");
     607                 :          0 :                 do_error(1);
     608                 :            :         }
     609                 :            : 
     610   [ #  #  #  # ]:          0 :         if(type_size(&(v->data_type), 0) == 4 && type_size(&t, 0) == 1){
     611         [ #  # ]:          0 :                 if(v->data.type == data_register){
     612                 :          0 :                         fileprint(output_file, "sll $s%d, $s%d, 24\n", v->data.reg, v->data.reg);
     613                 :          0 :                         fileprint(output_file, "sra $s%d, $s%d, 24\n", v->data.reg, v->data.reg);
     614         [ #  # ]:          0 :                 } else if(v->data.type == data_stack){
     615                 :          0 :                         fileprint(output_file, "lw $t0, %d($sp)\n", get_stack_pos(v->data));
     616                 :          0 :                         fileprint(output_file, "sll $t0, $t0, 24\n");
     617                 :          0 :                         fileprint(output_file, "sra $t0, $t0, 24\n");
     618                 :          0 :                         fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(v->data));
     619                 :            :                 }
     620   [ #  #  #  # ]:          0 :         } else if(type_size(&(v->data_type), 0) == 1 && type_size(&t, 0) == 4){
     621         [ #  # ]:          0 :                 if(v->data.type == data_stack){
     622                 :          0 :                         fileprint(output_file, "lb $t0, %d($sp)\n", get_stack_pos(v->data));
     623                 :          0 :                         fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(v->data));
     624                 :            :                 }
     625                 :            :         }
     626                 :            : 
     627                 :          0 :         t_copy = t;
     628                 :          0 :         entry1 = pop_type(&t_copy);
     629                 :          0 :         entry2 = pop_type(&(v->data_type));
     630   [ #  #  #  # ]:          0 :         if((entry1 == type_pointer) != (entry2 == type_pointer) && do_warn){
     631                 :          0 :                 snprintf(warning_message, sizeof(warning_message), "Casting between pointer and non-pointer types");
     632                 :          0 :                 do_warning();
     633   [ #  #  #  #  :          0 :         } else if(entry1 == type_pointer && !types_equal(&t_copy, &(v->data_type)) && !types_equal(&t_copy, &VOID_TYPE) && !types_equal(&(v->data_type), &VOID_TYPE) && do_warn){
          #  #  #  #  #  
                      # ]
     634                 :          0 :                 snprintf(warning_message, sizeof(warning_message), "Casting between incompatible pointer types");
     635                 :          0 :                 do_warning();
     636                 :            :         }
     637                 :            : 
     638                 :          0 :         v->data_type = t;
     639                 :          0 : }
     640                 :            : 
     641                 :          0 : void compile_dereference(value *v, FILE *output_file){
     642                 :          0 :         type data_type;
     643                 :            : 
     644                 :          0 :         data_type = v->data_type;
     645         [ #  # ]:          0 :         if(pop_type(&data_type) != type_pointer){
     646                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot dereference non-pointer type");
     647                 :          0 :                 do_error(1);
     648                 :            :         }
     649         [ #  # ]:          0 :         if(peek_type(&data_type) == type_void){
     650                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot dereference void pointer");
     651                 :          0 :                 do_error(1);
     652                 :            :         }
     653         [ #  # ]:          0 :         if(peek_type(&data_type) == type_list){
     654                 :          0 :                 pop_type(&data_type);
     655                 :          0 :                 data_type.current_index--;
     656                 :          0 :                 add_type_entry(&data_type, type_pointer);
     657         [ #  # ]:          0 :         } else if(peek_type(&data_type) != type_function){
     658         [ #  # ]:          0 :                 if(v->data.type == data_register){
     659         [ #  # ]:          0 :                         if(type_size(&data_type, 0) == 1){
     660                 :          0 :                                 fileprint(output_file, "lb $s%d, 0($s%d)\n", v->data.reg, v->data.reg);
     661         [ #  # ]:          0 :                         } else if(type_size(&data_type, 0) == 4){
     662                 :          0 :                                 fileprint(output_file, "lw $s%d, 0($s%d)\n", v->data.reg, v->data.reg);
     663                 :            :                         }
     664         [ #  # ]:          0 :                 } else if(v->data.type == data_stack){
     665                 :          0 :                         fileprint(output_file, "lw $t0, %d($sp)\n", get_stack_pos(v->data));
     666         [ #  # ]:          0 :                         if(type_size(&data_type, 0) == 1){
     667                 :          0 :                                 fileprint(output_file, "lb $t0, 0($t0)\n");
     668                 :          0 :                                 fileprint(output_file, "sb $t0, %d($sp)\n", get_stack_pos(v->data));
     669         [ #  # ]:          0 :                         } else if(type_size(&data_type, 0) == 4){
     670                 :          0 :                                 fileprint(output_file, "lw $t0, 0($t0)\n");
     671                 :          0 :                                 fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(v->data));
     672                 :            :                         }
     673                 :            :                 }
     674                 :            :         }
     675                 :            : 
     676                 :          0 :         v->data_type = data_type;
     677                 :          0 :         v->is_reference = 0;
     678                 :          0 : }
     679                 :            : 
     680                 :          0 : void compile_function_call(char **c, value *func, FILE *output_file){
     681                 :          0 :         reg_list reg_state;
     682                 :          0 :         data_entry return_data;
     683                 :          0 :         data_entry return_address_data;
     684                 :          0 :         type current_argument_type;
     685                 :          0 :         value current_argument_value;
     686                 :          0 :         unsigned int label_num;
     687                 :          0 :         int func_stack_pos = 0;
     688                 :          0 :         int any_args = 0;
     689                 :            : 
     690         [ #  # ]:          0 :         if(peek_type(&(func->data_type)) == type_pointer){
     691                 :          0 :                 pop_type(&(func->data_type));
     692                 :            :         }
     693         [ #  # ]:          0 :         if(pop_type(&(func->data_type)) != type_function){
     694                 :          0 :                 snprintf(error_message, sizeof(error_message), "Can't call non-function type");
     695                 :          0 :                 do_error(1);
     696                 :            :         }
     697                 :            : 
     698                 :          0 :         label_num = num_labels;
     699                 :          0 :         num_labels++;
     700                 :          0 :         reg_state = push_registers(output_file);
     701                 :            : 
     702         [ #  # ]:          0 :         if(func->data.type == data_register){
     703                 :          0 :                 func_stack_pos = get_reg_stack_pos(reg_state, func->data.reg);
     704                 :            :         }
     705                 :          0 :         return_address_data = allocate(1);
     706                 :          0 :         return_data = allocate(1);
     707                 :          0 :         fileprint(output_file, "la $t0, __L%d\n", label_num);
     708                 :          0 :         fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(return_address_data));
     709         [ #  # ]:          0 :         if(peek_type(&(func->data_type)) == type_returns){
     710                 :          0 :                 skip_whitespace(c);
     711         [ #  # ]:          0 :                 if(**c != ')'){
     712                 :          0 :                         snprintf(error_message, sizeof(error_message), "Expected ')'");
     713                 :          0 :                         do_error(1);
     714                 :            :                 }
     715                 :          0 :                 ++*c;
     716                 :            :         }
     717         [ #  # ]:          0 :         while(peek_type(&(func->data_type)) != type_returns){
     718                 :          0 :                 any_args = 1;
     719                 :          0 :                 current_argument_type = get_argument_type(&(func->data_type));
     720                 :          0 :                 compile_expression(&current_argument_value, c, 1, 1, output_file);
     721   [ #  #  #  # ]:          0 :                 if(**c != ',' && peek_type(&(func->data_type)) != type_returns){
     722                 :          0 :                         snprintf(error_message, sizeof(error_message), "Expected ','");
     723                 :          0 :                         do_error(1);
     724   [ #  #  #  # ]:          0 :                 } else if(**c != ')' && peek_type(&(func->data_type)) == type_returns){
     725                 :          0 :                         snprintf(error_message, sizeof(error_message), "Expected ')'");
     726                 :          0 :                         do_error(1);
     727                 :            :                 }
     728                 :          0 :                 ++*c;
     729                 :          0 :                 cast(&current_argument_value, current_argument_type, 1, output_file);
     730                 :            :         }
     731                 :            : 
     732                 :          0 :         pop_type(&(func->data_type));
     733         [ #  # ]:          0 :         if(func->data.type == data_register){
     734                 :          0 :                 fileprint(output_file, "lw $t0, %d($sp)\n", func_stack_pos);
     735         [ #  # ]:          0 :                 if(any_args)
     736                 :          0 :                         fileprint(output_file, "addi $sp, $sp, %d\n", get_stack_pos(current_argument_value.data));
     737                 :            :                 else
     738                 :          0 :                         fileprint(output_file, "addi $sp, $sp, %d\n", get_stack_pos(return_data));
     739                 :          0 :                 fileprint(output_file, "jr $t0\n\n");
     740         [ #  # ]:          0 :         } else if(func->data.type == data_stack){
     741                 :          0 :                 fileprint(output_file, "lw $t0, %d($sp)\n", get_stack_pos(func->data));
     742         [ #  # ]:          0 :                 if(any_args)
     743                 :          0 :                         fileprint(output_file, "addi $sp, $sp, %d\n", get_stack_pos(current_argument_value.data));
     744                 :            :                 else
     745                 :          0 :                         fileprint(output_file, "addi $sp, $sp, %d\n", get_stack_pos(return_data));
     746                 :          0 :                 fileprint(output_file, "jr $t0\n\n");
     747                 :            :         }
     748                 :          0 :         fileprint(output_file, "__L%d:\n", label_num);
     749         [ #  # ]:          0 :         if(any_args)
     750                 :          0 :                 fileprint(output_file, "addi $sp, $sp, %d\n", -get_stack_pos(current_argument_value.data));
     751                 :            :         else
     752                 :          0 :                 fileprint(output_file, "addi $sp, $sp, %d\n", -get_stack_pos(return_data));
     753                 :          0 :         fileprint(output_file, "lw $t0, %d($sp)\n", get_stack_pos(return_data));
     754                 :          0 :         deallocate(return_data);
     755                 :          0 :         deallocate(return_address_data);
     756                 :          0 :         pull_registers(reg_state, output_file);
     757         [ #  # ]:          0 :         if(func->data.type == data_register){
     758                 :          0 :                 fileprint(output_file, "move $s%d, $t0\n", func->data.reg);
     759         [ #  # ]:          0 :         } else if(func->data.type == data_stack){
     760                 :          0 :                 fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(func->data));
     761                 :            :         }
     762                 :          0 : }
     763                 :            : 
     764                 :          0 : void compile_list_index(char **c, value *address, unsigned char dereference, FILE *output_file){
     765                 :          0 :         value index;
     766                 :          0 :         type address_type;
     767                 :            : 
     768                 :          0 :         address_type = address->data_type;
     769         [ #  # ]:          0 :         if(pop_type(&address_type) != type_pointer){
     770                 :          0 :                 snprintf(error_message, sizeof(error_message), "Cannot address non-pointer type");
     771                 :          0 :                 do_error(1);
     772                 :            :         }
     773                 :          0 :         ++*c;
     774                 :          0 :         compile_expression(&index, c, 1, 0, output_file);
     775         [ #  # ]:          0 :         if(**c != ']'){
     776                 :          0 :                 snprintf(error_message, sizeof(error_message), "Expected closing ']'");
     777                 :          0 :                 do_error(1);
     778                 :            :         }
     779                 :          0 :         ++*c;
     780                 :          0 :         cast(&index, INT_TYPE, 1, output_file);
     781         [ #  # ]:          0 :         if(index.data.type == data_register){
     782         [ #  # ]:          0 :                 if(type_size(&address_type, 0) == 4){
     783                 :          0 :                         fileprint(output_file, "sll $s%d, $s%d, 2\n", index.data.reg, index.data.reg);
     784         [ #  # ]:          0 :                 } else if(type_size(&address_type, 0) != 1){
     785                 :          0 :                         fileprint(output_file, "li $t0, %d\n", (int) type_size(&address_type, 0));
     786                 :          0 :                         fileprint(output_file, "mult $s%d, $t0\n", index.data.reg);
     787                 :          0 :                         fileprint(output_file, "mflo $s%d\n", index.data.reg);
     788                 :            :                 }
     789         [ #  # ]:          0 :                 if(address->data.type == data_register){
     790                 :          0 :                         fileprint(output_file, "add $s%d, $s%d, $s%d\n", address->data.reg, address->data.reg, index.data.reg);
     791   [ #  #  #  # ]:          0 :                         if(dereference && peek_type(&address_type) != type_list){
     792         [ #  # ]:          0 :                                 if(type_size(&address_type, 0) == 4){
     793                 :          0 :                                         fileprint(output_file, "lw $s%d, 0($s%d)\n", address->data.reg, address->data.reg);
     794         [ #  # ]:          0 :                                 } else if(type_size(&address_type, 0) == 1){
     795                 :          0 :                                         fileprint(output_file, "lb $s%d, 0($s%d)\n", address->data.reg, address->data.reg);
     796                 :            :                                 } else {
     797                 :          0 :                                         snprintf(error_message, sizeof(error_message), "[INTERNAL] Unusable type size");
     798                 :          0 :                                         do_error(1);
     799                 :            :                                 }
     800                 :            :                         }
     801         [ #  # ]:          0 :                 } else if(address->data.type == data_stack){
     802                 :          0 :                         fileprint(output_file, "lw $t0, %d($sp)\n", get_stack_pos(address->data));
     803                 :          0 :                         fileprint(output_file, "add $t0, $t0, $s%d\n", index.data.reg);
     804   [ #  #  #  # ]:          0 :                         if(dereference && peek_type(&address_type) != type_list){
     805         [ #  # ]:          0 :                                 if(type_size(&address_type, 0) == 4){
     806                 :          0 :                                         fileprint(output_file, "lw $t0, 0($t0)\n");
     807         [ #  # ]:          0 :                                 } else if(type_size(&address_type, 0) == 1){
     808                 :          0 :                                         fileprint(output_file, "lb $t0, 0($t0)\n");
     809                 :            :                                 } else {
     810                 :          0 :                                         snprintf(error_message, sizeof(error_message), "[INTERNAL] Unusable type size");
     811                 :          0 :                                         do_error(1);
     812                 :            :                                 }
     813                 :            :                         }
     814                 :          0 :                         fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(address->data));
     815                 :            :                 }
     816         [ #  # ]:          0 :         } else if(index.data.type == data_stack){
     817                 :          0 :                 fileprint(output_file, "lw $t1, %d($sp)\n", get_stack_pos(index.data));
     818         [ #  # ]:          0 :                 if(type_size(&address_type, 0) == 4){
     819                 :          0 :                         fileprint(output_file, "sll $t1, $t1, 2\n");
     820         [ #  # ]:          0 :                 } else if(type_size(&address_type, 0) != 1){
     821                 :          0 :                         fileprint(output_file, "li $t0, %d\n", (int) type_size(&address_type, 0));
     822                 :          0 :                         fileprint(output_file, "mult $t1, $t0\n");
     823                 :          0 :                         fileprint(output_file, "mflo $t1\n");
     824                 :            :                 }
     825         [ #  # ]:          0 :                 if(address->data.type == data_register){
     826                 :          0 :                         fileprint(output_file, "add $s%d, $s%d, $t1\n", address->data.reg, address->data.reg);
     827   [ #  #  #  # ]:          0 :                         if(dereference && peek_type(&address_type) != type_list){
     828         [ #  # ]:          0 :                                 if(type_size(&address_type, 0) == 4){
     829                 :          0 :                                         fileprint(output_file, "lw $s%d, 0($s%d)\n", address->data.reg, address->data.reg);
     830         [ #  # ]:          0 :                                 } else if(type_size(&address_type, 0) == 1){
     831                 :          0 :                                         fileprint(output_file, "lb $s%d, 0($s%d)\n", address->data.reg, address->data.reg);
     832                 :            :                                 }
     833                 :            :                         }
     834         [ #  # ]:          0 :                 } else if(address->data.type == data_stack){
     835                 :          0 :                         fileprint(output_file, "lw $t0, %d($sp)\n", get_stack_pos(address->data));
     836                 :          0 :                         fileprint(output_file, "add $t0, $t0, $t1\n");
     837   [ #  #  #  # ]:          0 :                         if(dereference && peek_type(&address_type) != type_list){
     838         [ #  # ]:          0 :                                 if(type_size(&address_type, 0) == 4){
     839                 :          0 :                                         fileprint(output_file, "lw $t0, 0($t0)\n");
     840         [ #  # ]:          0 :                                 } else if(type_size(&address_type, 0) == 1){
     841                 :          0 :                                         fileprint(output_file, "lb $t0, 0($t0)\n");
     842                 :            :                                 }
     843                 :            :                         }
     844                 :          0 :                         fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(address->data));
     845                 :            :                 }
     846                 :            :         }
     847                 :          0 :         deallocate(index.data);
     848         [ #  # ]:          0 :         if(dereference){
     849                 :          0 :                 pop_type(&(address->data_type));
     850         [ #  # ]:          0 :                 if(peek_type(&(address->data_type)) == type_list){
     851                 :          0 :                         pop_type(&(address->data_type));
     852                 :          0 :                         address->data_type.current_index--;
     853                 :          0 :                         add_type_entry(&(address->data_type), type_pointer);
     854                 :            :                 }
     855                 :            :         }
     856                 :          0 :         address->is_reference = !dereference;
     857                 :          0 : }
     858                 :            : 
     859                 :            : void match_brackets(char **c);
     860                 :            : 
     861                 :          0 : void skip_string(char **c){
     862   [ #  #  #  #  :          0 :         while(**c && **c != '\"'){
          #  #  #  #  #  
                      # ]
     863   [ #  #  #  #  :          0 :                 if(**c == '\\'){
          #  #  #  #  #  
                      # ]
     864                 :          0 :                         *c += 2;
     865                 :            :                 } else {
     866                 :          0 :                         ++*c;
     867                 :            :                 }
     868                 :            :         }
     869   [ #  #  #  #  :          0 :         if(**c){
          #  #  #  #  #  
                      # ]
     870                 :          0 :                 ++*c;
     871                 :            :         }
     872                 :          0 : }
     873                 :            : 
     874                 :          0 : void match_parentheses(char **c){
     875   [ #  #  #  #  :          0 :         while(**c && **c != ')' && **c != ']'){
                   #  # ]
     876         [ #  # ]:          0 :                 if(**c == '"'){
     877                 :          0 :                         ++*c;
     878                 :          0 :                         skip_string(c);
     879                 :          0 :                         skip_whitespace(c);
     880                 :          0 :                         continue;
     881                 :            :                 }
     882         [ #  # ]:          0 :                 if(**c == '('){
     883                 :          0 :                         ++*c;
     884                 :          0 :                         match_parentheses(c);
     885         [ #  # ]:          0 :                 } else if(**c == '['){
     886                 :          0 :                         ++*c;
     887                 :          0 :                         match_brackets(c);
     888                 :            :                 } else {
     889                 :          0 :                         ++*c;
     890                 :            :                 }
     891                 :          0 :                 skip_whitespace(c);
     892                 :            :         }
     893   [ #  #  #  # ]:          0 :         if(!**c || **c == ']'){
     894                 :          0 :                 snprintf(error_message, sizeof(error_message), "Expected ')'");
     895                 :          0 :                 do_error(1);
     896                 :            :         }
     897                 :          0 :         ++*c;
     898                 :          0 : }
     899                 :            : 
     900                 :          0 : void match_brackets(char **c){
     901   [ #  #  #  #  :          0 :         while(**c && **c != ']' && **c != ')'){
                   #  # ]
     902         [ #  # ]:          0 :                 if(**c == '"'){
     903                 :          0 :                         ++*c;
     904                 :          0 :                         skip_string(c);
     905                 :          0 :                         skip_whitespace(c);
     906                 :          0 :                         continue;
     907                 :            :                 }
     908         [ #  # ]:          0 :                 if(**c == '('){
     909                 :          0 :                         ++*c;
     910                 :          0 :                         match_parentheses(c);
     911         [ #  # ]:          0 :                 } else if(**c == '['){
     912                 :          0 :                         ++*c;
     913                 :          0 :                         match_brackets(c);
     914                 :            :                 } else {
     915                 :          0 :                         ++*c;
     916                 :            :                 }
     917                 :          0 :                 skip_whitespace(c);
     918                 :            :         }
     919   [ #  #  #  # ]:          0 :         if(!**c || **c == ')'){
     920                 :          0 :                 snprintf(error_message, sizeof(error_message), "Expected ']'");
     921                 :          0 :                 do_error(1);
     922                 :            :         }
     923                 :          0 :         ++*c;
     924                 :          0 : }
     925                 :            : 
     926                 :          0 : void skip_comment(char **c){
     927                 :          0 :         ++*c;
     928         [ #  # ]:          0 :         if(**c == '/'){
     929   [ #  #  #  # ]:          0 :                 while(**c && **c != '\n'){
     930                 :          0 :                         ++*c;
     931                 :            :                 }
     932         [ #  # ]:          0 :                 if(**c){
     933                 :          0 :                         ++*c;
     934                 :            :                 }
     935                 :            :         } else {
     936                 :          0 :                 ++*c;
     937   [ #  #  #  #  :          0 :                 while(**c && (**c != '*' || (*c)[1] != '/')){
                   #  # ]
     938                 :          0 :                         ++*c;
     939                 :            :                 }
     940         [ #  # ]:          0 :                 if(**c){
     941                 :          0 :                         *c += 2;
     942                 :            :                 }
     943                 :            :         }
     944                 :          0 : }
     945                 :            : 
     946                 :          0 : unsigned char is_cast(char *c){
     947   [ #  #  #  # ]:          0 :         if(*c != '('){
     948                 :          0 :                 return 0;
     949                 :            :         }
     950                 :            : 
     951                 :          0 :         c++;
     952                 :          0 :         return parse_datatype(NULL, &c);
     953                 :            : }
     954                 :            : 
     955                 :          0 : void skip_value(char **c){
     956                 :          0 :         skip_whitespace(c);
     957   [ #  #  #  #  :          0 :         while(**c == '*' || **c == '&' || **c == '!' || **c == '~' || **c == '-' || is_cast(*c) || is_whitespace(*c)){
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     958         [ #  # ]:          0 :                 if(**c == '('){//ie if we are casting
     959                 :          0 :                         ++*c;
     960                 :          0 :                         match_parentheses(c);
     961         [ #  # ]:          0 :                 } else if(**c == '/'){
     962                 :          0 :                         skip_comment(c);
     963                 :            :                 } else {
     964                 :          0 :                         ++*c;
     965                 :            :                 }
     966                 :            :         }
     967         [ #  # ]:          0 :         while(**c == '('){
     968                 :          0 :                 ++*c;
     969                 :          0 :                 match_parentheses(c);
     970                 :          0 :                 skip_whitespace(c);
     971                 :            :         }
     972         [ #  # ]:          0 :         if(digit(**c)){
     973         [ #  # ]:          0 :                 while(digit(**c)){
     974                 :          0 :                         ++*c;
     975                 :            :                 }
     976         [ #  # ]:          0 :         } else if(alpha(**c)){
     977         [ #  # ]:          0 :                 while(alphanumeric(**c)){
     978                 :          0 :                         ++*c;
     979                 :            :                 }
     980         [ #  # ]:          0 :         } else if(**c == '\"'){
     981                 :          0 :                 ++*c;
     982                 :          0 :                 skip_string(c);
     983         [ #  # ]:          0 :         } else if(**c == '\''){
     984                 :          0 :                 ++*c;
     985         [ #  # ]:          0 :                 if(**c == '\\'){
     986                 :          0 :                         ++*c;
     987                 :            :                 }
     988   [ #  #  #  # ]:          0 :                 while(**c && **c != '\''){
     989                 :          0 :                         ++*c;
     990                 :            :                 }
     991         [ #  # ]:          0 :                 if(**c){
     992                 :          0 :                         ++*c;
     993                 :            :                 }
     994                 :            :         }
     995                 :          0 :         skip_whitespace(c);
     996   [ #  #  #  # ]:          0 :         while(**c == '[' || **c == '('){
     997         [ #  # ]:          0 :                 if(**c == '('){
     998                 :          0 :                         ++*c;
     999                 :          0 :                         match_parentheses(c);
    1000         [ #  # ]:          0 :                 } else if(**c == '['){
    1001                 :          0 :                         ++*c;
    1002                 :          0 :                         match_brackets(c);
    1003                 :            :                 }
    1004                 :          0 :                 skip_whitespace(c);
    1005                 :          0 :                 skip_whitespace(c);
    1006                 :            :         }
    1007                 :          0 : }
    1008                 :            : 
    1009                 :          0 : void compile_string(value *output, char **c, unsigned char dereference, unsigned char force_stack, FILE *output_file){
    1010                 :          0 :         ++*c;
    1011                 :          0 :         skip_string(c);
    1012                 :            : 
    1013                 :          0 :         output->data = allocate(force_stack);
    1014         [ #  # ]:          0 :         if(output->data.type == data_register){
    1015                 :          0 :                 fileprint(output_file, "la $s%d, __str%d\n", output->data.reg, current_string);
    1016         [ #  # ]:          0 :         } else if(output->data.type == data_stack){
    1017                 :          0 :                 fileprint(output_file, "la $t0, __str%d\n", current_string);
    1018                 :          0 :                 fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(output->data));
    1019                 :            :         }
    1020         [ #  # ]:          0 :         if(do_print)
    1021                 :          0 :                 current_string++;
    1022                 :          0 :         output->data_type = CHAR_TYPE;
    1023                 :          0 :         add_type_entry(&(output->data_type), type_pointer);
    1024                 :          0 :         output->is_reference = 0;
    1025                 :          0 : }
    1026                 :            : 
    1027                 :          0 : void compile_character(value *output, char **c, unsigned char dereference, unsigned char force_stack, FILE *output_file){
    1028                 :          0 :         int char_constant = 0;
    1029                 :          0 :         char escape_sequences[] = {'a', 'b', 'e', 'f', 'n', 'r', 't', 'v', '\\', '\'', '\"', '\?'};
    1030                 :          0 :         int escape_values[] = {0x07, 0x08, 0x1B, 0x0C, 0x0A, 0x0D, 0x09, 0x0B, 0x5C, 0x27, 0x22, 0x3F};
    1031                 :          0 :         unsigned char i;
    1032                 :            : 
    1033                 :          0 :         ++*c;
    1034                 :            : 
    1035         [ #  # ]:          0 :         if(**c == '\\'){
    1036                 :          0 :                 ++*c;
    1037         [ #  # ]:          0 :                 for(i = 0; i < sizeof(escape_sequences)/sizeof(char); i++){
    1038         [ #  # ]:          0 :                         if(**c == escape_sequences[i]){
    1039                 :          0 :                                 char_constant = escape_values[i];
    1040                 :            :                         }
    1041                 :            :                 }
    1042         [ #  # ]:          0 :                 if(!char_constant){
    1043                 :          0 :                         snprintf(error_message, sizeof(error_message), "Unrecognized escape sequence\n");
    1044                 :          0 :                         do_error(1);
    1045                 :            :                 }
    1046                 :            :         } else {
    1047                 :          0 :                 char_constant = **c;
    1048                 :            :         }
    1049                 :          0 :         ++*c;
    1050         [ #  # ]:          0 :         if(**c != '\''){
    1051                 :          0 :                 snprintf(error_message, sizeof(error_message), "Expected closing '\n");
    1052                 :          0 :                 do_error(1);
    1053                 :            :         }
    1054                 :          0 :         ++*c;
    1055                 :            : 
    1056                 :          0 :         output->data = allocate(force_stack);
    1057         [ #  # ]:          0 :         if(output->data.type == data_register){
    1058                 :          0 :                 fileprint(output_file, "li $s%d, %d\n", output->data.reg, char_constant);
    1059         [ #  # ]:          0 :         } else if(output->data.type == data_stack){
    1060                 :          0 :                 fileprint(output_file, "li $t0, %d\n", char_constant);
    1061                 :          0 :                 fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(output->data));
    1062                 :            :         }
    1063                 :          0 :         output->data_type = INT_TYPE;
    1064                 :          0 :         output->is_reference = 0;
    1065                 :          0 : }
    1066                 :            : 
    1067                 :          0 : void compile_logical_not(value *v, FILE *output_file){
    1068                 :          0 :         int size;
    1069                 :            : 
    1070         [ #  # ]:          0 :         if(v->data.type == data_register){
    1071                 :          0 :                 fileprint(output_file, "seq $s%d, $s%d, $zero\n", v->data.reg, v->data.reg);
    1072         [ #  # ]:          0 :         } else if(v->data.type == data_stack){
    1073                 :          0 :                 size = type_size(&(v->data_type), 0);
    1074         [ #  # ]:          0 :                 if(size == 4){
    1075                 :          0 :                         fileprint(output_file, "lw $t0, %d($sp)\n", get_stack_pos(v->data));
    1076         [ #  # ]:          0 :                 } else if(size == 1){
    1077                 :          0 :                         fileprint(output_file, "lb $t0, %d($sp)\n", get_stack_pos(v->data));
    1078                 :            :                 }
    1079                 :          0 :                 fileprint(output_file, "seq $t0, $t0, $zero\n");
    1080                 :          0 :                 fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(v->data));
    1081                 :            :         }
    1082                 :            : 
    1083                 :          0 :         v->data_type = INT_TYPE;
    1084                 :          0 : }
    1085                 :            : 
    1086                 :          0 : void compile_not(value *v, FILE *output_file){
    1087                 :          0 :         int size;
    1088                 :            : 
    1089   [ #  #  #  # ]:          0 :         if(!types_equal(&(v->data_type), &INT_TYPE) && !types_equal(&(v->data_type), &CHAR_TYPE)){
    1090                 :          0 :                 snprintf(error_message, sizeof(error_message), "Can't perform bitwise not of non-numerical type");
    1091                 :          0 :                 do_error(1);
    1092                 :            :         }
    1093         [ #  # ]:          0 :         if(v->data.type == data_register){
    1094                 :          0 :                 fileprint(output_file, "nor $s%d, $s%d, $s%d\n", v->data.reg, v->data.reg, v->data.reg);
    1095         [ #  # ]:          0 :         } else if(v->data.type == data_stack){
    1096                 :          0 :                 size = type_size(&(v->data_type), 0);
    1097         [ #  # ]:          0 :                 if(size == 4){
    1098                 :          0 :                         fileprint(output_file, "lw $t0, %d($sp)\n", get_stack_pos(v->data));
    1099         [ #  # ]:          0 :                 } else if(size == 1){
    1100                 :          0 :                         fileprint(output_file, "lb $t0, %d($sp)\n", get_stack_pos(v->data));
    1101                 :            :                 }
    1102                 :          0 :                 fileprint(output_file, "nor $t0, $t0, $t0\n");
    1103                 :          0 :                 fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(v->data));
    1104                 :            :         }
    1105                 :            : 
    1106                 :          0 :         v->data_type = INT_TYPE;
    1107                 :          0 : }
    1108                 :            : 
    1109                 :          0 : void compile_negate(value *v, FILE *output_file){
    1110                 :          0 :         int size;
    1111                 :            : 
    1112   [ #  #  #  # ]:          0 :         if(!types_equal(&(v->data_type), &INT_TYPE) && !types_equal(&(v->data_type), &CHAR_TYPE)){
    1113                 :          0 :                 snprintf(error_message, sizeof(error_message), "Can't negate non-numerical type");
    1114                 :          0 :                 do_error(1);
    1115                 :            :         }
    1116         [ #  # ]:          0 :         if(v->data.type == data_register){
    1117                 :          0 :                 fileprint(output_file, "sub $s%d, $zero, $s%d\n", v->data.reg, v->data.reg);
    1118         [ #  # ]:          0 :         } else if(v->data.type == data_stack){
    1119                 :          0 :                 size = type_size(&(v->data_type), 0);
    1120         [ #  # ]:          0 :                 if(size == 4){
    1121                 :          0 :                         fileprint(output_file, "lw $t0, %d($sp)\n", get_stack_pos(v->data));
    1122         [ #  # ]:          0 :                 } else if(size == 1){
    1123                 :          0 :                         fileprint(output_file, "lb $t0, %d($sp)\n", get_stack_pos(v->data));
    1124                 :            :                 }
    1125                 :          0 :                 fileprint(output_file, "sub $t0, $zero, $t0\n");
    1126                 :          0 :                 fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(v->data));
    1127                 :            :         }
    1128                 :            : 
    1129                 :          0 :         v->data_type = INT_TYPE;
    1130                 :          0 : }
    1131                 :            : 
    1132                 :          0 : void compile_value(value *output, char **c, unsigned char dereference, unsigned char force_stack, FILE *output_file){
    1133                 :          0 :         char *temp_c;
    1134                 :          0 :         type cast_type;
    1135                 :            : 
    1136                 :          0 :         skip_whitespace(c);
    1137                 :            : 
    1138         [ #  # ]:          0 :         if(**c == '*'){
    1139                 :          0 :                 ++*c;
    1140                 :          0 :                 compile_value(output, c, 1, force_stack, output_file);
    1141         [ #  # ]:          0 :                 if(dereference){
    1142                 :          0 :                         compile_dereference(output, output_file);
    1143                 :            :                 }
    1144                 :          0 :                 output->is_reference = !dereference;
    1145                 :          0 :                 return;
    1146         [ #  # ]:          0 :         } else if(**c == '&'){
    1147                 :          0 :                 ++*c;
    1148         [ #  # ]:          0 :                 if(dereference){
    1149                 :          0 :                         compile_value(output, c, 0, force_stack, output_file);
    1150                 :            :                 } else {
    1151                 :          0 :                         snprintf(error_message, sizeof(error_message), "Can't get address of r-value");
    1152                 :          0 :                         do_error(1);
    1153                 :            :                 }
    1154                 :          0 :                 output->is_reference = 0;
    1155                 :          0 :                 return;
    1156         [ #  # ]:          0 :         } else if(**c == '!'){
    1157                 :          0 :                 ++*c;
    1158         [ #  # ]:          0 :                 if(dereference){
    1159                 :          0 :                         compile_value(output, c, 1, force_stack, output_file);
    1160                 :          0 :                         compile_logical_not(output, output_file);
    1161                 :            :                 } else {
    1162                 :          0 :                         snprintf(error_message, sizeof(error_message), "Can't get address of r-value");
    1163                 :          0 :                         do_error(1);
    1164                 :            :                 }
    1165                 :          0 :                 output->is_reference = 0;
    1166                 :          0 :                 return;
    1167         [ #  # ]:          0 :         } else if(**c == '~'){
    1168                 :          0 :                 ++*c;
    1169         [ #  # ]:          0 :                 if(dereference){
    1170                 :          0 :                         compile_value(output, c, 1, force_stack, output_file);
    1171                 :          0 :                         compile_not(output, output_file);
    1172                 :            :                 } else {
    1173                 :          0 :                         snprintf(error_message, sizeof(error_message), "Can't get address of r-value");
    1174                 :          0 :                         do_error(1);
    1175                 :            :                 }
    1176                 :          0 :                 output->is_reference = 0;
    1177                 :          0 :                 return;
    1178   [ #  #  #  # ]:          0 :         } else if(**c == '-' && !digit((*c)[1])){
    1179                 :          0 :                 ++*c;
    1180         [ #  # ]:          0 :                 if(dereference){
    1181                 :          0 :                         compile_value(output, c, 1, force_stack, output_file);
    1182                 :          0 :                         compile_negate(output, output_file);
    1183                 :            :                 } else {
    1184                 :          0 :                         snprintf(error_message, sizeof(error_message), "Can't get address of r-value");
    1185                 :          0 :                         do_error(1);
    1186                 :            :                 }
    1187                 :          0 :                 output->is_reference = 0;
    1188                 :          0 :                 return;
    1189                 :            :         }
    1190                 :            : 
    1191         [ #  # ]:          0 :         if(**c == '('){
    1192                 :          0 :                 ++*c;
    1193                 :          0 :                 skip_whitespace(c);
    1194                 :          0 :                 temp_c = *c;
    1195                 :            :                 //Type casting
    1196         [ #  # ]:          0 :                 if(parse_datatype(NULL, &temp_c)){
    1197                 :          0 :                         cast_type = EMPTY_TYPE;
    1198                 :          0 :                         parse_type(&cast_type, c, NULL, NULL, 0, 0);
    1199         [ #  # ]:          0 :                         if(**c != ')'){
    1200                 :          0 :                                 snprintf(error_message, sizeof(error_message), "Expected ')'");
    1201                 :          0 :                                 do_error(1);
    1202                 :            :                         }
    1203                 :          0 :                         ++*c;
    1204                 :          0 :                         compile_value(output, c, 1, force_stack, output_file);
    1205                 :          0 :                         cast(output, cast_type, 0, output_file);
    1206                 :            :                 //Associative parentheses
    1207                 :            :                 } else {
    1208                 :          0 :                         compile_expression(output, c, dereference, force_stack, output_file);
    1209         [ #  # ]:          0 :                         if(**c == ')'){
    1210                 :          0 :                                 ++*c;
    1211                 :            :                         } else {
    1212                 :          0 :                                 snprintf(error_message, sizeof(error_message), "Expected closing ')'");
    1213                 :          0 :                                 do_error(1);
    1214                 :            :                         }
    1215                 :            :                 }
    1216   [ #  #  #  # ]:          0 :         } else if(**c == '-' || digit(**c)){
    1217                 :          0 :                 compile_integer(output, c, dereference, force_stack, output_file);
    1218         [ #  # ]:          0 :         } else if(alpha(**c)){
    1219                 :          0 :                 compile_variable(output, c, dereference, force_stack, output_file);
    1220         [ #  # ]:          0 :         } else if(**c == '\"'){
    1221                 :          0 :                 compile_string(output, c, dereference, force_stack, output_file);
    1222         [ #  # ]:          0 :         } else if(**c == '\''){
    1223                 :          0 :                 compile_character(output, c, dereference, force_stack, output_file);
    1224                 :            :         } else {
    1225                 :          0 :                 snprintf(error_message, sizeof(error_message), "Unrecognized expression value");
    1226                 :          0 :                 do_error(1);
    1227                 :            :         }
    1228                 :            : 
    1229                 :          0 :         skip_whitespace(c);
    1230   [ #  #  #  # ]:          0 :         while(**c == '[' || **c == '('){
    1231         [ #  # ]:          0 :                 if(**c == '['){
    1232         [ #  # ]:          0 :                         if(output->is_reference){
    1233                 :          0 :                                 compile_dereference(output, output_file);
    1234                 :            :                         }
    1235                 :          0 :                         compile_list_index(c, output, dereference, output_file);
    1236         [ #  # ]:          0 :                 } else if(**c == '('){
    1237                 :          0 :                         ++*c;
    1238         [ #  # ]:          0 :                         if(output->is_reference){
    1239                 :          0 :                                 compile_dereference(output, output_file);
    1240                 :            :                         }
    1241                 :          0 :                         compile_function_call(c, output, output_file);
    1242                 :            :                 }
    1243                 :            : 
    1244                 :          0 :                 skip_whitespace(c);
    1245                 :            :         }
    1246                 :            : }
    1247                 :            : 
    1248                 :          0 : operation peek_operation(char *c){
    1249   [ #  #  #  #  :          0 :         switch(*c){
          #  #  #  #  #  
                #  #  # ]
    1250                 :          0 :                 case '+':
    1251                 :          0 :                         return operation_add;
    1252                 :          0 :                 case '-':
    1253                 :          0 :                         return operation_subtract;
    1254                 :          0 :                 case '*':
    1255                 :          0 :                         return operation_multiply;
    1256                 :          0 :                 case '/':
    1257                 :          0 :                         return operation_divide;
    1258                 :          0 :                 case '%':
    1259                 :          0 :                         return operation_modulo;
    1260                 :          0 :                 case '=':
    1261         [ #  # ]:          0 :                         if(c[1] == '='){
    1262                 :          0 :                                 return operation_equals;
    1263                 :            :                         } else {
    1264                 :          0 :                                 return operation_assign;
    1265                 :            :                         }
    1266                 :          0 :                 case '!':
    1267         [ #  # ]:          0 :                         if(c[1] == '='){
    1268                 :          0 :                                 return operation_not_equals;
    1269                 :            :                         } else {
    1270                 :          0 :                                 return operation_none;
    1271                 :            :                         }
    1272                 :          0 :                 case '>':
    1273         [ #  # ]:          0 :                         if(c[1] == '>'){
    1274                 :          0 :                                 return operation_shift_right;
    1275         [ #  # ]:          0 :                         } else if(c[1] == '='){
    1276                 :          0 :                                 return operation_greater_than_or_equal;
    1277                 :            :                         } else {
    1278                 :          0 :                                 return operation_greater_than;
    1279                 :            :                         }
    1280                 :          0 :                 case '<':
    1281         [ #  # ]:          0 :                         if(c[1] == '<'){
    1282                 :          0 :                                 return operation_shift_left;
    1283         [ #  # ]:          0 :                         } else if(c[1] == '='){
    1284                 :          0 :                                 return operation_less_than_or_equal;
    1285                 :            :                         } else {
    1286                 :          0 :                                 return operation_less_than;
    1287                 :            :                         }
    1288                 :          0 :                 case '&':
    1289         [ #  # ]:          0 :                         if(c[1] == '&'){
    1290                 :          0 :                                 return operation_logical_and;
    1291                 :            :                         } else {
    1292                 :          0 :                                 return operation_and;
    1293                 :            :                         }
    1294                 :          0 :                 case '|':
    1295         [ #  # ]:          0 :                         if(c[1] == '|'){
    1296                 :          0 :                                 return operation_logical_or;
    1297                 :            :                         } else {
    1298                 :          0 :                                 return operation_or;
    1299                 :            :                         }
    1300                 :            :         }
    1301                 :            : 
    1302                 :          0 :         return operation_none;
    1303                 :            : }
    1304                 :            : 
    1305                 :          0 : operation get_operation(char **c){
    1306                 :          0 :         operation output;
    1307                 :            : 
    1308                 :          0 :         skip_whitespace(c);
    1309   [ #  #  #  #  :          0 :         switch(**c){
          #  #  #  #  #  
                #  #  # ]
    1310                 :          0 :                 case '+':
    1311                 :          0 :                         output = operation_add;
    1312                 :          0 :                         break;
    1313                 :          0 :                 case '-':
    1314                 :          0 :                         output = operation_subtract;
    1315                 :          0 :                         break;
    1316                 :          0 :                 case '*':
    1317                 :          0 :                         output = operation_multiply;
    1318                 :          0 :                         break;
    1319                 :          0 :                 case '/':
    1320                 :          0 :                         output = operation_divide;
    1321                 :          0 :                         break;
    1322                 :          0 :                 case '%':
    1323                 :          0 :                         output = operation_modulo;
    1324                 :          0 :                         break;
    1325                 :          0 :                 case '=':
    1326         [ #  # ]:          0 :                         if((*c)[1] == '='){
    1327                 :          0 :                                 output = operation_equals;
    1328                 :          0 :                                 ++*c;
    1329                 :            :                         } else {
    1330                 :          0 :                                 output = operation_assign;
    1331                 :            :                         }
    1332                 :          0 :                         break;
    1333                 :          0 :                 case '!':
    1334         [ #  # ]:          0 :                         if((*c)[1] == '='){
    1335                 :          0 :                                 output = operation_not_equals;
    1336                 :          0 :                                 ++*c;
    1337                 :            :                         } else {
    1338                 :          0 :                                 output = operation_none;
    1339                 :            :                         }
    1340                 :          0 :                         break;
    1341                 :          0 :                 case '>':
    1342         [ #  # ]:          0 :                         if((*c)[1] == '>'){
    1343                 :          0 :                                 output = operation_shift_right;
    1344                 :          0 :                                 ++*c;
    1345         [ #  # ]:          0 :                         } else if((*c)[1] == '='){
    1346                 :          0 :                                 output = operation_greater_than_or_equal;
    1347                 :          0 :                                 ++*c;
    1348                 :            :                         } else {
    1349                 :          0 :                                 output = operation_greater_than;
    1350                 :            :                         }
    1351                 :          0 :                         break;
    1352                 :          0 :                 case '<':
    1353         [ #  # ]:          0 :                         if((*c)[1] == '<'){
    1354                 :          0 :                                 output = operation_shift_left;
    1355                 :          0 :                                 ++*c;
    1356         [ #  # ]:          0 :                         } else if((*c)[1] == '='){
    1357                 :          0 :                                 output = operation_less_than_or_equal;
    1358                 :          0 :                                 ++*c;
    1359                 :            :                         } else {
    1360                 :          0 :                                 output = operation_less_than;
    1361                 :            :                         }
    1362                 :          0 :                         break;
    1363                 :          0 :                 case '&':
    1364         [ #  # ]:          0 :                         if((*c)[1] == '&'){
    1365                 :          0 :                                 output = operation_logical_and;
    1366                 :          0 :                                 ++*c;
    1367                 :            :                         } else {
    1368                 :          0 :                                 output = operation_and;
    1369                 :            :                         }
    1370                 :          0 :                         break;
    1371                 :          0 :                 case '|':
    1372         [ #  # ]:          0 :                         if((*c)[1] == '|'){
    1373                 :          0 :                                 output = operation_logical_or;
    1374                 :          0 :                                 ++*c;
    1375                 :            :                         } else {
    1376                 :          0 :                                 output = operation_or;
    1377                 :            :                         }
    1378                 :          0 :                         break;
    1379                 :          0 :                 default:
    1380                 :          0 :                         output = operation_none;
    1381                 :          0 :                         break;
    1382                 :            :         }
    1383                 :          0 :         ++*c;
    1384                 :          0 :         return output;
    1385                 :            : }
    1386                 :            : 
    1387                 :          0 : void compile_operation(value *first_value, value *next_value, operation op, FILE *output_file){
    1388                 :          0 :         char reg0_str_buffer[5] = {0, 0, 0, 0, 0};
    1389                 :          0 :         char reg1_str_buffer[5] = {0, 0, 0, 0, 0};
    1390                 :          0 :         char *reg0_str = "";
    1391                 :          0 :         char *reg1_str = "";
    1392                 :          0 :         type output_type;
    1393                 :            : 
    1394   [ #  #  #  # ]:          0 :         if(types_equal(&(first_value->data_type), &VOID_TYPE) || types_equal(&(next_value->data_type), &VOID_TYPE)){
    1395                 :          0 :                 snprintf(error_message, sizeof(error_message), "Can't operate on void value");
    1396                 :          0 :                 do_error(1);
    1397                 :            :         }
    1398                 :            : 
    1399         [ #  # ]:          0 :         if(first_value->data.type == data_register){
    1400                 :          0 :                 snprintf(reg0_str_buffer, sizeof(reg0_str_buffer)/sizeof(char), "$s%d", first_value->data.reg);
    1401                 :          0 :                 reg0_str = reg0_str_buffer;
    1402         [ #  # ]:          0 :         } else if(first_value->data.type == data_stack){
    1403                 :          0 :                 reg0_str = "$t0";
    1404         [ #  # ]:          0 :                 if(type_size(&(first_value->data_type), 0) == 4){
    1405                 :          0 :                         fileprint(output_file, "lw $t0, %d($sp)\n", get_stack_pos(first_value->data));
    1406         [ #  # ]:          0 :                 } else if(type_size(&(first_value->data_type), 0) == 1){
    1407                 :          0 :                         fileprint(output_file, "lb $t0, %d($sp)\n", get_stack_pos(first_value->data));
    1408                 :            :                 } else {
    1409                 :          0 :                         snprintf(error_message, sizeof(error_message), "[INTERNAL] Unusable type size %d", type_size(&(first_value->data_type), 0));
    1410                 :          0 :                         do_error(1);
    1411                 :            :                 }
    1412                 :            :         }
    1413         [ #  # ]:          0 :         if(next_value->data.type == data_register){
    1414                 :          0 :                 snprintf(reg1_str_buffer, sizeof(reg1_str_buffer)/sizeof(char), "$s%d", next_value->data.reg);
    1415                 :          0 :                 reg1_str = reg1_str_buffer;
    1416         [ #  # ]:          0 :         } else if(next_value->data.type == data_stack){
    1417                 :          0 :                 reg1_str = "$t1";
    1418         [ #  # ]:          0 :                 if(type_size(&(next_value->data_type), 0) == 4){
    1419                 :          0 :                         fileprint(output_file, "lw $t1, %d($sp)\n", get_stack_pos(next_value->data));
    1420         [ #  # ]:          0 :                 } else if(type_size(&(next_value->data_type), 0) == 1){
    1421                 :          0 :                         fileprint(output_file, "lb $t1, %d($sp)\n", get_stack_pos(next_value->data));
    1422                 :            :                 } else {
    1423                 :          0 :                         snprintf(error_message, sizeof(error_message), "[INTERNAL] Unusable type size %d", type_size(&(next_value->data_type), 0));
    1424                 :          0 :                         do_error(1);
    1425                 :            :                 }
    1426                 :            :         }
    1427                 :          0 :         operation_functions[op](reg0_str, reg1_str, first_value, next_value, output_file, &output_type);
    1428                 :          0 :         deallocate(next_value->data);
    1429         [ #  # ]:          0 :         if(first_value->data.type == data_stack){
    1430         [ #  # ]:          0 :                 if(type_size(&output_type, 0) == 4){
    1431                 :          0 :                         fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(first_value->data));
    1432         [ #  # ]:          0 :                 } else if(type_size(&output_type, 0) == 1){
    1433                 :          0 :                         fileprint(output_file, "sb $t0, %d($sp)\n", get_stack_pos(first_value->data));
    1434                 :            :                 } else {
    1435                 :          0 :                         snprintf(error_message, sizeof(error_message), "[INTERNAL] Unusable type size %d", type_size(&output_type, 0));
    1436                 :          0 :                         do_error(1);
    1437                 :            :                 }
    1438                 :            :         }
    1439                 :          0 :         first_value->data_type = output_type;
    1440                 :          0 :         first_value->is_reference = 0;
    1441                 :          0 : }
    1442                 :            : 
    1443                 :          0 : static void compile_expression_recursive(value *first_value, char **c, FILE *output_file){
    1444                 :          0 :         operation current_operation;
    1445                 :          0 :         operation next_operation;
    1446                 :          0 :         unsigned int label_num = 0;
    1447                 :          0 :         value next_value;
    1448                 :          0 :         char *temp_c;
    1449                 :          0 :         type cast_to;
    1450                 :          0 :         int current_line_temp;
    1451                 :            : 
    1452                 :          0 :         skip_whitespace(c);
    1453                 :          0 :         current_operation = get_operation(c);
    1454         [ #  # ]:          0 :         if(current_operation == operation_none){
    1455                 :          0 :                 snprintf(error_message, sizeof(error_message), "Unrecognized operation");
    1456                 :          0 :                 do_error(1);
    1457         [ #  # ]:          0 :         } else if(current_operation == operation_logical_or){
    1458                 :          0 :                 label_num = num_labels;
    1459                 :          0 :                 num_labels++;
    1460                 :          0 :                 cast(first_value, INT_TYPE, 0, output_file);
    1461         [ #  # ]:          0 :                 if(first_value->data.type == data_register){
    1462                 :          0 :                         fileprint(output_file, "sne $s%d, $s%d, $zero\n", first_value->data.reg, first_value->data.reg);
    1463                 :          0 :                         fileprint(output_file, "bne $s%d, $zero, __L%d\n", first_value->data.reg, label_num);
    1464         [ #  # ]:          0 :                 } else if(first_value->data.type == data_stack){
    1465                 :          0 :                         fileprint(output_file, "lw $t0, %d($sp)\n", get_stack_pos(first_value->data));
    1466                 :          0 :                         fileprint(output_file, "sne $t0, $t0, $zero\n");
    1467                 :          0 :                         fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(first_value->data));
    1468                 :          0 :                         fileprint(output_file, "bne $t0, $zero, __L%d\n", label_num);
    1469                 :            :                 }
    1470         [ #  # ]:          0 :         } else if(current_operation == operation_logical_and){
    1471                 :          0 :                 label_num = num_labels;
    1472                 :          0 :                 num_labels++;
    1473                 :          0 :                 cast(first_value, INT_TYPE, 0, output_file);
    1474         [ #  # ]:          0 :                 if(first_value->data.type == data_register){
    1475                 :          0 :                         fileprint(output_file, "beq $s%d, $zero, __L%d\n", first_value->data.reg, label_num);
    1476         [ #  # ]:          0 :                 } else if(first_value->data.type == data_stack){
    1477                 :          0 :                         fileprint(output_file, "lw $t0, %d($sp)\n", get_stack_pos(first_value->data));
    1478                 :          0 :                         fileprint(output_file, "beq $t0, $zero, __L%d\n", label_num);
    1479                 :            :                 }
    1480                 :            :         }
    1481                 :            : 
    1482                 :          0 :         temp_c = *c;
    1483                 :          0 :         current_line_temp = current_line;
    1484                 :          0 :         skip_value(&temp_c);
    1485                 :          0 :         current_line = current_line_temp;
    1486                 :          0 :         next_operation = peek_operation(temp_c);
    1487   [ #  #  #  # ]:          0 :         if(next_operation == operation_assign && order_of_operations[operation_assign] > order_of_operations[current_operation]){
    1488                 :          0 :                 compile_value(&next_value, c, 0, 0, output_file);
    1489                 :            :         } else {
    1490                 :          0 :                 compile_value(&next_value, c, 1, 0, output_file);
    1491                 :            :         }
    1492                 :          0 :         skip_whitespace(c);
    1493         [ #  # ]:          0 :         while(order_of_operations[next_operation] > order_of_operations[current_operation]){
    1494                 :          0 :                 compile_expression_recursive(&next_value, c, output_file);
    1495                 :          0 :                 skip_whitespace(c);
    1496                 :          0 :                 next_operation = peek_operation(*c);
    1497                 :            :         }
    1498         [ #  # ]:          0 :         if(current_operation == operation_assign){
    1499                 :          0 :                 cast_to = first_value->data_type;
    1500                 :          0 :                 pop_type(&cast_to);
    1501                 :          0 :                 cast(&next_value, cast_to, 1, output_file);
    1502                 :          0 :                 compile_operation(first_value, &next_value, current_operation, output_file);
    1503   [ #  #  #  # ]:          0 :         } else if(current_operation == operation_logical_or || current_operation == operation_logical_and){
    1504                 :          0 :                 cast(&next_value, INT_TYPE, 0, output_file);
    1505         [ #  # ]:          0 :                 if(next_value.data.type == data_register){
    1506                 :          0 :                         fileprint(output_file, "sne $s%d, $s%d, $zero\n", next_value.data.reg, next_value.data.reg);
    1507         [ #  # ]:          0 :                         if(first_value->data.type == data_register){
    1508                 :          0 :                                 fileprint(output_file, "move $s%d, $s%d\n", first_value->data.reg, next_value.data.reg);
    1509         [ #  # ]:          0 :                         } else if(first_value->data.type == data_stack){
    1510                 :          0 :                                 fileprint(output_file, "sw $s%d, %d($sp)\n", next_value.data.reg, get_stack_pos(first_value->data));
    1511                 :            :                         }
    1512         [ #  # ]:          0 :                 } else if(next_value.data.type == data_stack){
    1513         [ #  # ]:          0 :                         if(first_value->data.type == data_register){
    1514                 :          0 :                                 fileprint(output_file, "lw $s%d, %d($sp)\n", first_value->data.reg, get_stack_pos(next_value.data));
    1515                 :          0 :                                 fileprint(output_file, "sne $s%d, $s%d, $zero\n", first_value->data.reg, first_value->data.reg);
    1516         [ #  # ]:          0 :                         } else if(first_value->data.type == data_stack){
    1517                 :          0 :                                 fileprint(output_file, "lw $t0, %d($sp)\n", get_stack_pos(next_value.data));
    1518                 :          0 :                                 fileprint(output_file, "sne $t0, $t0, $zero\n");
    1519                 :          0 :                                 fileprint(output_file, "sw $t0, %d($sp)\n", get_stack_pos(first_value->data));
    1520                 :            :                         }
    1521                 :            :                 }
    1522                 :          0 :                 deallocate(next_value.data);
    1523                 :          0 :                 fileprint(output_file, "\n__L%d:\n", label_num);
    1524                 :            :         } else {
    1525                 :          0 :                 compile_operation(first_value, &next_value, current_operation, output_file);
    1526                 :            :         }
    1527                 :          0 :         skip_whitespace(c);
    1528                 :          0 : }
    1529                 :            : 
    1530                 :          0 : void compile_expression(value *first_value, char **c, unsigned char dereference, unsigned char force_stack, FILE *output_file){
    1531                 :          0 :         char *temp_c;
    1532                 :          0 :         int current_line_temp;
    1533                 :          0 :         operation next_operation;
    1534                 :            : 
    1535                 :          0 :         temp_c = *c;
    1536                 :          0 :         current_line_temp = current_line;
    1537                 :          0 :         skip_value(&temp_c);
    1538                 :          0 :         current_line = current_line_temp;
    1539                 :            : 
    1540                 :          0 :         next_operation = peek_operation(temp_c);
    1541         [ #  # ]:          0 :         if(peek_operation(temp_c) == operation_assign){
    1542                 :          0 :                 compile_value(first_value, c, 0, force_stack, output_file);
    1543                 :            :         } else {
    1544   [ #  #  #  # ]:          0 :                 compile_value(first_value, c, dereference || next_operation != operation_none, force_stack, output_file);
    1545                 :            :         }
    1546   [ #  #  #  #  :          0 :         while(**c && **c != ';' && **c != ',' && **c != ')' && **c != ']'){
          #  #  #  #  #  
                      # ]
    1547                 :          0 :                 compile_expression_recursive(first_value, c, output_file);
    1548                 :            :         }
    1549                 :          0 : }
    1550                 :            : 
    1551                 :          0 : void determine_stack_size(value *first_value, char **c, unsigned char dereference, unsigned char force_stack){
    1552                 :          0 :         char *temp_c;
    1553                 :            : 
    1554                 :          0 :         do_print = 0;
    1555                 :          0 :         saved_stack_size = 0;
    1556                 :          0 :         temp_c = *c;
    1557                 :          0 :         compile_expression(first_value, c, dereference, force_stack, NULL);
    1558                 :          0 :         *c = temp_c;
    1559                 :          0 :         do_print = 1;
    1560                 :          0 : }
    1561                 :            : 
    1562                 :          0 : void compile_root_expression(value *first_value, char **c, unsigned char dereference, unsigned char force_stack, FILE *output_file){
    1563                 :          0 :         determine_stack_size(first_value, c, dereference, force_stack);
    1564                 :          0 :         deallocate(first_value->data);
    1565         [ #  # ]:          0 :         if(saved_stack_size != 0){
    1566                 :          0 :                 fprintf(output_file, "addi $sp, $sp, %d\n", -saved_stack_size);
    1567                 :            :         }
    1568                 :          0 :         compile_expression(first_value, c, dereference, force_stack, output_file);
    1569                 :          0 : }
    1570                 :            : 
    1571                 :            : //THIS MUST ALWAYS BE CALLED AFTER COMPILE_ROOT_EXPRESSION IS RUN AGAIN!
    1572                 :            : //It is not included in compile_root_expression just in case the caller wants to first cast the return value of compile_root_expression
    1573                 :            : //If compile_root_expression did do that, then such a cast either would not work or would be past the bounds of the stack
    1574                 :          0 : void reset_stack_pos(value *first_value, FILE *output_file){
    1575         [ #  # ]:          0 :         if(first_value->data.type == data_stack){
    1576                 :          0 :                 fprintf(output_file, "lw $t0, %d($sp)\n", get_stack_pos(first_value->data));
    1577                 :            :         }
    1578         [ #  # ]:          0 :         if(saved_stack_size != 0){
    1579                 :          0 :                 fprintf(output_file, "addi $sp, $sp, %d\n", saved_stack_size);
    1580                 :            :         }
    1581                 :          0 : }

Generated by: LCOV version 1.14