void BFInterpreter_compile(BFInterpreter *interpreter, FILE *input_file) { int pc = 0; int c = 0; char current_char; while ((c = fgetc(input_file)) != EOF) { if (pc > MAX_TAPE_SIZE-1) { printf("Program is larger than the tape size. Exiting...\n"); exit(1); } current_char = (char) c; #ifdef DEBUG printf("Current token is: %c\n", current_char); #endif if ((current_char == '+') || (current_char == '-') || (current_char == '>') || (current_char == '<') || (current_char == '.') || (current_char == ',')) { interpreter->program_tape[pc].type = SIMPLE; interpreter->program_tape[pc].Instruction.SimpleInstruction.opcode = current_char; pc++; } if (current_char == '[') { Stack_push(&interpreter->jump_locations, pc); interpreter->program_tape[pc].type = JUMP; interpreter->program_tape[pc].Instruction.JumpInstruction.opcode = current_char; pc++; } if (current_char == ']') { if (Stack_empty(&interpreter->jump_locations)) { printf("Unmatched loop instruction!\n"); exit(1); } unsigned int jl = Stack_pop(&interpreter->jump_locations); interpreter->program_tape[pc].type = JUMP; interpreter->program_tape[pc].Instruction.JumpInstruction.opcode = current_char; interpreter->program_tape[pc].Instruction.JumpInstruction.jump_location = jl; interpreter->program_tape[jl].Instruction.JumpInstruction.jump_location = pc; #ifdef DEBUG printf("Instruction at program_tape[%d] will jump to location: %d\n", pc, jl); printf("Instruction at program_tape[%d] will jump to location: %d\n", jl, pc); #endif pc++; } } if (!Stack_empty(&interpreter->jump_locations)) { printf("Unmatched loop instruction!\n"); exit(1); } }
AP_T pop(void) { if (!Stack_empty(sp)) return Stack_pop(sp); else { Fmt_fprint(stderr, "?stack underflow\n"); return AP_new(0); } }
void free_IDs(Stack_T unmapped_IDs) { uint32_t *ID; while (!Stack_empty(unmapped_IDs)) { ID = Stack_pop(unmapped_IDs); FREE(ID); } Stack_free(&unmapped_IDs); }
void *Stack_pop(T stk) { struct elem *e = NULL; if (Stack_empty(stk) != 0) return NULL; e = stk->head; stk->head = stk->head->link; stk->count--; void *p = e->x; free(e); return p; }
/* * create a segment with the size of nums, and return the index of the segs of * the mapped segment. There are two conditons, if the unmapped stack is not * empty, we reuse the segment index stored in unmapped stack and pop that out. * otherwise we just create a new segments and addhi into segs, the return index * is the length of segs. */ uint32_t map_segment(Mem myMem, uint32_t nums) { assert(myMem != NULL); Segment_T newSeg = Seg_new(nums); for (uint32_t i = 0; i < nums; i++) { Seq_addhi((Seq_T)newSeg, (void*) (uintptr_t) 0); } uint32_t index; if (Stack_empty(myMem->unmapped) == 1) { Seq_addhi(myMem->segs, (void*) newSeg); index = Seq_length(myMem->segs) - 1; } else { index = (int) (uintptr_t) Stack_pop(myMem->unmapped); Seg_free(Seq_put(myMem->segs, index, (void*) newSeg)); }; return index; }
int main(int argc, char *argv[]) { int c; sp = Stack_new(); Fmt_register('D', AP_fmt); while ((c = getchar()) != EOF) switch (c) { case ' ': case '\t': case '\n': case '\f': case '\r': break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { char buf[512]; { int i = 0; for ( ; c != EOF && isdigit(c); c = getchar(), i++) if (i < (int)sizeof (buf) - 1) buf[i] = c; if (i > (int)sizeof (buf) - 1) { i = (int)sizeof (buf) - 1; Fmt_fprint(stderr, "?integer constant exceeds %d digits\n", i); } buf[i] = 0; if (c != EOF) ungetc(c, stdin); } Stack_push(sp, AP_fromstr(buf, 10, NULL)); break; } case '+': { AP_T y = pop(), x = pop(); Stack_push(sp, AP_add(x, y)); AP_free(&x); AP_free(&y); break; } case '-': { AP_T y = pop(), x = pop(); Stack_push(sp, AP_sub(x, y)); AP_free(&x); AP_free(&y); break; } case '*': { AP_T y = pop(), x = pop(); Stack_push(sp, AP_mul(x, y)); AP_free(&x); AP_free(&y); break; } case '/': { AP_T y = pop(), x = pop(); if (AP_cmpi(y, 0) == 0) { Fmt_fprint(stderr, "?/ by 0\n"); Stack_push(sp, AP_new(0)); } else Stack_push(sp, AP_div(x, y)); AP_free(&x); AP_free(&y); break; } case '%': { AP_T y = pop(), x = pop(); if (AP_cmpi(y, 0) == 0) { Fmt_fprint(stderr, "?%% by 0\n"); Stack_push(sp, AP_new(0)); } else Stack_push(sp, AP_mod(x, y)); AP_free(&x); AP_free(&y); break; } case '^': { AP_T y = pop(), x = pop(); if (AP_cmpi(y, 0) <= 0) { Fmt_fprint(stderr, "?nonpositive power\n"); Stack_push(sp, AP_new(0)); } else Stack_push(sp, AP_pow(x, y, NULL)); AP_free(&x); AP_free(&y); break; } case 'd': { AP_T x = pop(); Stack_push(sp, x); Stack_push(sp, AP_addi(x, 0)); break; } case 'p': { AP_T x = pop(); Fmt_print("%D\n", x); Stack_push(sp, x); break; } case 'f': if (!Stack_empty(sp)) { Stack_T tmp = Stack_new(); while (!Stack_empty(sp)) { AP_T x = pop(); Fmt_print("%D\n", x); Stack_push(tmp, x); } while (!Stack_empty(tmp)) Stack_push(sp, Stack_pop(tmp)); Stack_free(&tmp); } break; case '~': { AP_T x = pop(); Stack_push(sp, AP_neg(x)); AP_free(&x); break; } case 'c': while (!Stack_empty(sp)) { AP_T x = Stack_pop(sp); AP_free(&x); } break; case 'q': while (!Stack_empty(sp)) { AP_T x = Stack_pop(sp); AP_free(&x); } Stack_free(&sp); return EXIT_SUCCESS; default: if (isprint(c)) Fmt_fprint(stderr, "?'%c'", c); else Fmt_fprint(stderr, "?'\\%03o'", c); Fmt_fprint(stderr, " is unimplemented\n"); break; } while (!Stack_empty(sp)) { AP_T x = Stack_pop(sp); AP_free(&x); } Stack_free(&sp); return EXIT_SUCCESS; }
void execute_program(UM_state um) { int ra =0; int rb =0; int rc =0; //uint32_t val= 0; bool proceed = true; int num_instructions = get_words_in_seg(um->memory, 0); int i = um->instr_ctr; while (i < num_instructions && proceed) { uint32_t word = get_word(um->memory, 0, i); uint32_t op_code = get_op_code(word); /*if (op_code == 13) { int ra = get_reg_num(word, LOAD_RA_LSB); proceed &= valid_reg(ra); uint32_t val = get_val(word); (void) val; } else {*/ ra = get_reg_num(word, RA_LSB); rb = get_reg_num(word, RB_LSB); rc = get_reg_num(word, RC_LSB); proceed &= valid_reg(ra); proceed &= valid_reg(rb); proceed &= valid_reg(rc); //} if (!proceed) { break; } if (op_code == 0) { /* Conditional move - op code 0 */ if (val_in_reg(um, rc) != 0) { uint32_t val = val_in_reg(um, rb); set_reg_val(um, ra, val); } } else if (op_code == 1) { /* Segmented load - op code 1 */ uint32_t val = get_word(um->memory, val_in_reg(um, rb), val_in_reg(um, rc)); set_reg_val(um, ra, val); } else if (op_code == 2) { /* Segmented store - op code 2 */ uint32_t ID = val_in_reg(um, ra); uint32_t offset = val_in_reg(um, rb); uint32_t val = val_in_reg(um, rc); put_word(um->memory, ID, offset, val); } else if (op_code == 3) { /* Add - op code 3 */ uint32_t val = (val_in_reg(um, rb) + val_in_reg(um, rc)) % UINT_MAX; set_reg_val(um, ra, val); } else if (op_code == 4) { /* Multiply - op code 4 */ uint32_t val = (val_in_reg(um, rb) * val_in_reg(um, rc)) % UINT_MAX; set_reg_val(um, ra, val); } else if (op_code == 5) { /* Divide - op code 5 */ uint32_t val = val_in_reg(um, rb) / val_in_reg(um, rc); set_reg_val(um, ra, val); } else if (op_code == 6) { /* Bitwise NAND - op code 6 */ uint32_t val = ~(val_in_reg(um, rb) & val_in_reg(um, rc)); set_reg_val(um, ra, val); } else if (op_code == 7) { /* Halt */ proceed = false; } else if (op_code == 8) { /* Map segment - op code 8 */ if (Stack_empty(um->unmapped_IDs)) { uint32_t num_words = val_in_reg(um, rc); proceed &= create_segment(um->memory, num_words); set_reg_val(um, rb, (get_num_segs(um->memory) - 1)); } else { uint32_t ID = get_unmapped_ID(um); uint32_t num_words = val_in_reg(um, rc); proceed &= resize(um->memory, ID, num_words); set_reg_val(um, rb, ID); } } else if (op_code == 9) { /* Unmap segment - op code 9 */ uint32_t ID = val_in_reg(um, rc); proceed &= clear_seg(um->memory, ID); proceed &= add_unmapped_ID(um, ID); } else if (op_code == 10) { /* Output - op code 10 */ uint32_t val = val_in_reg(um, rc); if (val < 256) { fprintf(stdout, "%c", (char) val); } else { proceed &= false; } } else if (op_code == 11) { /* Input - op code 11 */ uint32_t val = getc(stdin); if ((int) val == EOF) { val = ~0; } else if (val > 255) { proceed &= false; } set_reg_val(um, rc, val); } else if (op_code == 12) { /* Load program - op code 12 */ uint32_t ID = val_in_reg(um, rb); if (ID != 0) { proceed &= clear_seg(um->memory, 0); int num_words = get_words_in_seg(um->memory, ID); resize(um->memory, 0, num_words); for (int i = 0; i < num_words; i++) { proceed &= put_word(um->memory, 0, i, get_word(um->memory, ID, i)); } } um->instr_ctr = val_in_reg(um, rc); num_instructions = get_words_in_seg(um->memory, 0); i = um->instr_ctr; } else if (op_code == 13) { /* Load value - op code 13 */ ra = get_reg_num(word, LOAD_RA_LSB); proceed &= valid_reg(ra); uint32_t val = get_val(word); set_reg_val(um, ra, val); } else { fprintf(stderr, "op code doesn't exist\n"); proceed = false; } if (op_code != 12) { i++; } } return; }