interpreter

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

interpreter.h (17696B)


      1 #ifndef AWA_INTERPRETER_H_
      2 #define AWA_INTERPRETER_H_
      3 
      4 #include "common.h"
      5 
      6 static void awa_recursive_bubble_free(awa_bubble_t* bubble) {
      7     if (bubble) {
      8         for (awa_bubble_t *next, *b = bubble->first; b; b = next) {
      9             next = b->next;
     10             awa_recursive_bubble_free(b);
     11         }
     12         free(bubble);
     13     }
     14 }
     15 #define bubble_pop(prog) do {                       \
     16         awa_bubble_t* tmp = (prog)->bubble_first;   \
     17         llist_stack_pop((prog)->bubble_first);      \
     18         tmp->next = NULL;                           \
     19         awa_recursive_bubble_free(tmp);             \
     20     } while (0);
     21 
     22 
     23 static void awa_recursive_print_bubble(awa_bubble_t* bubble) {
     24     if (bubble->first) {
     25         for (awa_bubble_t* b = bubble->first; b; b = b->next) {
     26             awa_recursive_print_bubble(b);
     27         }
     28     } else {
     29         if (bubble->val <= 63)
     30             putchar(awascii_table[bubble->val]);
     31     }
     32 }
     33 static void awa_recursive_print_num_bubble(awa_bubble_t* bubble, bool first) {
     34     if (bubble->first) {
     35         for (awa_bubble_t* b = bubble->first; b; b = b->next) {
     36             awa_recursive_print_num_bubble(b, false);
     37         }
     38     } else {
     39         if (!first) putchar(' ');
     40         printf("%d", bubble->val);
     41     }
     42 }
     43 
     44 static void awa_recursive_bubble_deep_copy(awa_bubble_t* to, awa_bubble_t* from) {
     45     for (awa_bubble_t* from_inside = from->first; from_inside; from_inside = from_inside->next) {
     46         awa_bubble_t* b = calloc(sizeof(*b), 1);
     47         awa_recursive_bubble_deep_copy(b, from_inside);
     48         llist_queue_push(to->first, to->last, b);
     49     }
     50     to->val = from->val;
     51 }
     52 
     53 enum awa_arithmetic_op {
     54     AWA_ARITH_ADD,
     55     AWA_ARITH_SUB,
     56     AWA_ARITH_MUL,
     57     AWA_ARITH_DIV,
     58 };
     59 static void awa_bubble_arithmetic_val(awa_bubble_t* new, awa_bubble_t* a, awa_bubble_t* b, enum awa_arithmetic_op op) {
     60     switch(op) {
     61     case AWA_ARITH_ADD: new->val = a->val + b->val; break;
     62     case AWA_ARITH_SUB: new->val = a->val - b->val; break;
     63     case AWA_ARITH_MUL: new->val = a->val * b->val; break;
     64     case AWA_ARITH_DIV: {
     65         awa_bubble_t* res = calloc(sizeof(*res), 1);
     66         res->val = a->val / b->val;
     67         awa_bubble_t* rem = calloc(sizeof(*rem), 1);
     68         rem->val = a->val % b->val;
     69         llist_queue_push(new->first, new->last, res);
     70         llist_queue_push(new->first, new->last, rem);
     71         break;
     72     }
     73     }
     74 }
     75 
     76 static awa_bubble_t* awa_recursive_bubble_arithmetic(awa_bubble_t* a, awa_bubble_t* b, enum awa_arithmetic_op op) {
     77     awa_bubble_t* new = calloc(sizeof(*new), 1);
     78     if (!a->first && !b->first) {
     79         awa_bubble_arithmetic_val(new, a, b, op);
     80     } else if (a->first && !b->first) {
     81         for (awa_bubble_t* a_inside = a->first; a_inside; a_inside = a_inside->next) {
     82             awa_bubble_t* new_inside = awa_recursive_bubble_arithmetic(a_inside, b, op);
     83             llist_queue_push(new->first, new->last, new_inside);
     84         }
     85     } else if (!a->first && b->first) {
     86         for (awa_bubble_t* b_inside = b->first; b_inside; b_inside = b_inside->next) {
     87             awa_bubble_t* new_inside = awa_recursive_bubble_arithmetic(a, b_inside, op);
     88             llist_queue_push(new->first, new->last, new_inside);
     89         }
     90     } else {
     91         for (awa_bubble_t* b_inside = b->first, *a_inside = a->first; b_inside && a_inside; b_inside = b_inside->next, a_inside = a_inside->next) {
     92             awa_bubble_t* new_inside = awa_recursive_bubble_arithmetic(a_inside, b_inside, op);
     93             llist_queue_push(new->first, new->last, new_inside);
     94         }
     95     }
     96     return new;
     97 }
     98 
     99 static void awa_bubble_arithmetic(awa_program_t* program, enum awa_arithmetic_op op) {
    100     if (program->bubble_first) {
    101         if (program->bubble_first->next) {
    102             awa_bubble_t* new = awa_recursive_bubble_arithmetic(program->bubble_first, program->bubble_first->next, op);
    103             new->next = program->bubble_first->next->next;
    104 
    105             awa_recursive_bubble_free(program->bubble_first->next);
    106             awa_recursive_bubble_free(program->bubble_first);
    107             program->bubble_first = new;
    108         }
    109     }
    110 }
    111 
    112 enum awa_cmp_op {
    113     AWA_CMP_EQ,
    114     AWA_CMP_LESS,
    115     AWA_CMP_GRTR,
    116 };
    117 static bool awa_bubble_cmp_val(awa_bubble_t* a, awa_bubble_t* b, enum awa_cmp_op op) {
    118     switch(op) {
    119     case AWA_CMP_EQ: return a->val == b->val;
    120     case AWA_CMP_LESS: return a->val < b->val;
    121     case AWA_CMP_GRTR: return a->val > b->val;
    122     }
    123     return false;
    124 }
    125 static bool awa_recursive_bubble_cmp(awa_bubble_t* a, awa_bubble_t* b, enum awa_cmp_op op) {
    126     if (!a->first && !b->first) {
    127         if (!awa_bubble_cmp_val(a, b, op))
    128             return false;
    129     } else if (a->first && !b->first) {
    130         for (awa_bubble_t* a_inside = a->first; a_inside; a_inside = a_inside->next) {
    131             if (!awa_recursive_bubble_cmp(a_inside, b, op))
    132                 return false;
    133         }
    134     } else if (!a->first && b->first) {
    135         for (awa_bubble_t* b_inside = b->first; b_inside; b_inside = b_inside->next) {
    136             if (!awa_recursive_bubble_cmp(a, b_inside, op))
    137                 return false;
    138         }
    139     } else {
    140         awa_bubble_t* b_inside = b->first, *a_inside = a->first;
    141         for (; b_inside && a_inside; b_inside = b_inside->next, a_inside = a_inside->next) {
    142             if (!awa_recursive_bubble_cmp(a_inside, b_inside, op))
    143                 return false;
    144         }
    145         if (a_inside != b_inside)
    146             return false;
    147     }
    148     return true;
    149 }
    150 static void awa_bubble_cmp(awa_program_t* program, enum awa_cmp_op op) {
    151     if (program->bubble_first) {
    152         if (program->bubble_first->next) {
    153             if (!awa_recursive_bubble_cmp(program->bubble_first, program->bubble_first->next, op)) {
    154                 program->cmp_skip_next_flag = true;
    155             }
    156         }
    157     }
    158 }
    159 
    160 static size_t awa_recursive_get_bubble_count(awa_bubble_t* bubble) {
    161     if (bubble->first) {
    162         size_t count = 0;
    163         for (awa_bubble_t* b = bubble->first; b; b = b->next)
    164             count += awa_recursive_get_bubble_count(b);
    165         return count;
    166     } else {
    167         return 1;
    168     }
    169 }
    170 static void awa_recursive_to_bytes(awa_bubble_t* bubble, uint8_t** bytes) {
    171     if (bubble->first) {
    172         for (awa_bubble_t* b = bubble->first; b; b = b->next)
    173             awa_recursive_to_bytes(b, bytes);
    174     } else {
    175         **bytes = bubble->val;
    176         *bytes += 1;
    177     }
    178 }
    179 static size_t awa_get_syscall_param(bool* is_ptr_out, awa_bubble_t* bubble) {
    180     if (bubble->first) {
    181         size_t count = awa_recursive_get_bubble_count(bubble);
    182         uint8_t* ptr = malloc(count);
    183         {
    184             uint8_t* tmp = ptr;
    185             awa_recursive_to_bytes(bubble, &tmp);
    186         }
    187         *is_ptr_out = true;
    188         return (size_t)ptr;
    189     } else {
    190         *is_ptr_out = false;
    191         return bubble->val;
    192     }
    193 }
    194 
    195 static void awa_program_run(awa_program_t program, bool print_debug, bool step_through, bool enable_syscalls) {
    196     for (awatism_t* current_awatism = program.awatism_first; current_awatism; current_awatism = current_awatism->next) {
    197     rerun_current_awatism:;
    198         if (print_debug) {
    199             printf("\t<<<");
    200             printf("(");
    201             for (awa_bubble_t* b = program.bubble_first; b; b = b->next) {
    202                 if (b != program.bubble_first) printf(", ");
    203                 awa_recursive_debug_print_bubble(b);
    204             }
    205             printf(")");
    206             printf(" | ");
    207             awa_print_awatism(*current_awatism);
    208             if (program.cmp_skip_next_flag)
    209             printf(" | SKIPPING");
    210             printf(">>>\n");
    211         }
    212         if (step_through)
    213             getchar();
    214 
    215         if (program.cmp_skip_next_flag) {
    216             program.cmp_skip_next_flag = false;
    217             continue;
    218         }
    219         switch((enum awatisms)current_awatism->opcode) {
    220         case AWA_NOP: {
    221             // nothing
    222         } break;
    223         case AWA_PRINT: {
    224             if (program.bubble_first) {
    225                 awa_recursive_print_bubble(program.bubble_first);
    226                 program.last_print_was_number_flag = false;
    227                 bubble_pop(&program);
    228             }
    229         } break;
    230         case AWA_PRINT_NUM: {
    231             if (program.bubble_first) {
    232                 awa_recursive_print_num_bubble(program.bubble_first, !program.last_print_was_number_flag);
    233                 program.last_print_was_number_flag = true;
    234                 bubble_pop(&program);
    235             }
    236         } break;
    237         case AWA_READ: {
    238             printf(">>>AWA INTERPRETER IS REQUESTING INPUT(text): ");
    239             char buf[1024] = {0};
    240             fgets(buf, sizeof(buf), stdin);
    241             int i = 0;
    242             awa_bubble_t* new = calloc(sizeof(*new), 1);
    243             for (; buf[i] && buf[i] != '\n'; i++) {
    244                 uint8_t c = awascii_table_inverse[(uint8_t)buf[i]];
    245                 if (c && buf[i] != 'A') {
    246                     awa_bubble_t* b = calloc(sizeof(*b), 1);
    247                     b->val = c;
    248                     llist_queue_push(new->first, new->last, b);
    249                 }
    250             }
    251             if (new->first) llist_stack_push(program.bubble_first, new);
    252             else            free(new);
    253             printf(">>>AWA INTERPRETER READ INPUT [%.*s]\n", i, buf);
    254         } break;
    255         case AWA_READ_NUM: {
    256             printf(">>>AWA INTERPRETER IS REQUESTING INPUT(numb): ");
    257             char buf[1024] = {0};
    258             fgets(buf, sizeof(buf), stdin);
    259             awa_bubble_t* b = calloc(sizeof(*b), 1);
    260             sscanf(buf, "%d", &b->val);
    261             llist_stack_push(program.bubble_first, b);
    262             printf(">>>AWA INTERPRETER READ INPUT [%d]\n", b->val);
    263         } break;
    264         case AWA_TERMINATE: {
    265             goto program_end;
    266         } break;
    267         case AWA_BLOW: {
    268             awa_bubble_t* b = calloc(sizeof(*b), 1);
    269             b->val = current_awatism->s8;
    270             llist_stack_push(program.bubble_first, b);
    271         } break;
    272         case AWA_SUBMERGE: {
    273             if (program.bubble_first && program.bubble_first->next) {
    274                 awa_bubble_t* sub = program.bubble_first;
    275                 int depth = current_awatism->u8;
    276                 llist_stack_pop(program.bubble_first);
    277 
    278                 awa_bubble_t* last = program.bubble_first;
    279                 int i = 1;
    280                 for (awa_bubble_t* b = last->next; b && i != depth; b = b->next, i++) {
    281                     last = b;
    282                 }
    283                 sub->next = last->next;
    284                 last->next = sub;
    285             }
    286         } break;
    287         case AWA_POP: {
    288             if (program.bubble_first) {
    289                 awa_bubble_t* tmp = program.bubble_first;
    290                 llist_stack_pop(program.bubble_first);
    291                 if (tmp->first) {
    292                     while (tmp->first) {
    293                         if (tmp->first->next == NULL) {
    294                             llist_stack_push(program.bubble_first, tmp->first);
    295                             break;
    296                         }
    297                         for (awa_bubble_t* b = tmp->first; b; b = b->next) {
    298                             if (b->next->next == NULL) {
    299                                 llist_stack_push(program.bubble_first, b->next);
    300                                 b->next = NULL;
    301                                 break;
    302                             }
    303                         }
    304                     }
    305                 }
    306                 free(tmp);
    307             }
    308         } break;
    309         case AWA_DUPLICATE: {
    310             if (program.bubble_first) {
    311                 awa_bubble_t* b = calloc(sizeof(*b), 1);
    312                 awa_recursive_bubble_deep_copy(b, program.bubble_first);
    313                 llist_stack_push(program.bubble_first, b);
    314             }
    315         } break;
    316         case AWA_SURROUND: {
    317             if (program.bubble_first && current_awatism->u8) {
    318                 awa_bubble_t* b = calloc(sizeof(*b), 1);
    319                 for (int i = 0; i < current_awatism->u8; i++) {
    320                     awa_bubble_t* b_inside = program.bubble_first;
    321                     if (!b_inside) break;
    322                     llist_stack_pop(program.bubble_first);
    323                     b_inside->next = NULL;
    324                     llist_queue_push(b->first, b->last, b_inside);
    325                 }
    326                 llist_stack_push(program.bubble_first, b);
    327             }
    328         } break;
    329         case AWA_MERGE: {
    330             awa_bubble_t* two[2];
    331             if (program.bubble_first) {
    332                 two[0] = program.bubble_first;
    333                 if (program.bubble_first->next) {
    334                     two[1] = program.bubble_first->next;
    335 
    336                     if (!two[0]->first && !two[1]->first) {
    337                         two[0]->val += two[1]->val;
    338                         two[0]->next = two[1]->next;
    339                         free(two[1]);
    340                     } else {
    341                         awa_bubble_t* new = calloc(sizeof(*new), 1);
    342                         new->next = two[1]->next;
    343                         program.bubble_first = new;
    344 
    345                         for (int i = 0; i < 2; i++) {
    346                             if (two[i]->first) {
    347                                 for (awa_bubble_t* next, *b = two[i]->first; b; b = next) {
    348                                     next = b->next;
    349                                     llist_queue_push(new->first, new->last, b);
    350                                 }
    351                                 free(two[i]);
    352                             } else {
    353                                 llist_queue_push(new->first, new->last, two[i]);
    354                             }
    355                         }
    356                     }
    357                 }
    358             }
    359         } break;
    360         case AWA_ADD: {
    361             awa_bubble_arithmetic(&program, AWA_ARITH_ADD);
    362         } break;
    363         case AWA_SUBTRACT: {
    364             awa_bubble_arithmetic(&program, AWA_ARITH_SUB);
    365         } break;
    366         case AWA_MULTIPLY: {
    367             awa_bubble_arithmetic(&program, AWA_ARITH_MUL);
    368         } break;
    369         case AWA_DIVIDE: {
    370             awa_bubble_arithmetic(&program, AWA_ARITH_DIV);
    371         } break;
    372         case AWA_COUNT: {
    373             if (program.bubble_first) {
    374                 int count = 0;
    375                 for (awa_bubble_t* b = program.bubble_first->first; b; b = b->next) {
    376                     count++;
    377                 }
    378                 awa_bubble_t* b = calloc(sizeof(*b), 1);
    379                 b->val = count;
    380                 llist_stack_push(program.bubble_first, b);
    381             }
    382         } break;
    383         case AWA_LABEL: {
    384             // nothing
    385         } break;
    386         case AWA_JUMP: {
    387             if (program.awalabel_table[current_awatism->u8]) {
    388                 current_awatism = program.awalabel_table[current_awatism->u8];
    389                 goto rerun_current_awatism;
    390             } else {
    391                 awa_debug_printf("interpreter: unable to find label %d\n", current_awatism->u8);
    392             }
    393         } break;
    394         case AWA_EQUAL_TO: {
    395             awa_bubble_cmp(&program, AWA_CMP_EQ);
    396         } break;
    397         case AWA_LESS_THAN: {
    398             awa_bubble_cmp(&program, AWA_CMP_LESS);
    399         } break;
    400         case AWA_GREATER_THAN: {
    401             awa_bubble_cmp(&program, AWA_CMP_GRTR);
    402         } break;
    403         case AWA_SYSCALL: {
    404 #ifndef awa_syscall
    405             awa_debug_printf("syscalls are not supported on this platform, terminating\n");
    406             goto program_end;
    407 #endif
    408             if (!enable_syscalls) {
    409                 awa_debug_printf("syscalls are intentionally disabled!");
    410                 goto program_end;
    411             }
    412             if (program.bubble_first) {
    413                 int count = 0;
    414                 for (awa_bubble_t* b = program.bubble_first->first; b; b = b->next)
    415                     count++;
    416                 if (count > 0 && count <= 7) {
    417                     size_t args[6] = {0};
    418                     bool is_ptr[6] = {0};
    419                     {
    420                         awa_bubble_t* b = program.bubble_first->first;
    421                         for (int i = 0; i < count; i++, b = b->next)
    422                             args[i] = awa_get_syscall_param(&is_ptr[i], b);
    423                     }
    424 
    425                     long val = -1;
    426                     switch(count) {
    427                     case 1: val = awa_syscall(current_awatism->u16, args[0]); break;
    428                     case 2: val = awa_syscall(current_awatism->u16, args[0], args[1]); break;
    429                     case 3: val = awa_syscall(current_awatism->u16, args[0], args[1], args[2]); break;
    430                     case 4: val = awa_syscall(current_awatism->u16, args[0], args[1], args[2], args[3]); break;
    431                     case 5: val = awa_syscall(current_awatism->u16, args[0], args[1], args[2], args[3], args[4]); break;
    432                     case 6: val = awa_syscall(current_awatism->u16, args[0], args[1], args[2], args[3], args[4], args[5]); break;
    433                     }
    434 
    435                     for (int i = 0; i < count; i++)
    436                         if (is_ptr[i]) free((void*)args[i]);
    437                     awa_bubble_t* n = calloc(sizeof(*n), 1);
    438                     n->val = val;
    439                     llist_stack_push(program.bubble_first, n);
    440                 } else {
    441                     awa_debug_printf("syscall(%d) had an invalid number of arguments %d\n", current_awatism->u16, count);
    442                     goto program_end;
    443                 }
    444             }
    445         } break;
    446         case AWA_DOUBLE_POP: {
    447             if (program.bubble_first)
    448                 bubble_pop(&program);
    449         } break;
    450         default: {
    451             awa_debug_printf("interpreter: invalid opcode %d\n", current_awatism->opcode);
    452         } break;
    453         }
    454     }
    455 program_end:;
    456     while(program.bubble_first)
    457         bubble_pop(&program);
    458 }
    459 
    460 
    461 #endif // AWA_INTERPRETER_H_