X-Git-Url: http://git.subgeniuskitty.com/vvhitespace/.git/blobdiff_plain/1adfc4f47354f613475855e2cf21f6cb87043410..66af3009b12b115d5744460c72f52e37fb6dee09:/vv_interpreter.c diff --git a/vv_interpreter.c b/vv_interpreter.c index 8f98fec..8d4db24 100644 --- a/vv_interpreter.c +++ b/vv_interpreter.c @@ -21,10 +21,10 @@ void print_usage(char ** argv) { - printf( "Whitespace Interpreter v%d (www.subgeniuskitty.com)\n" + printf( "VVhitespace Interpreter v%d (www.subgeniuskitty.com)\n" "Usage: %s -i \n" " -h Help (prints this message)\n" - " -i Specify a Whitespace source file to interpret.\n" + " -i Specify a VVhitespace source file to interpret.\n" , VERSION, argv[0] ); } @@ -49,7 +49,6 @@ stdin_empty(void) void ws_die(size_t * pc, char * msg) { - printf("\n"); printf("SIM_ERROR @ PC %lu: %s\n", *pc, msg); fflush(stdout); exit(EXIT_FAILURE); @@ -80,6 +79,10 @@ next_code_byte(uint8_t * code, size_t * pc) return code[(*pc)++]; } +/* + * In addition to returning the parsed label, this function advances the PC to + * the next instruction. + */ uint16_t parse_label(uint8_t * code, size_t * pc) { @@ -89,9 +92,24 @@ parse_label(uint8_t * code, size_t * pc) label = label << 1; if (c == ' ') label++; } + // TODO: Where should I handle attempts to access an unitialized label? + // For now, leave it undefined in a nasal demon sense. return label; } +void +populate_labels(uint32_t * labels, uint8_t * code, size_t code_size) +{ + size_t cp = 0; + while (cp <= code_size) { + if (code[cp] == '\v') { + uint16_t temp_label = parse_label(code, &cp); + labels[temp_label] = cp; + } + cp++; + } +} + void process_imp_stack(uint8_t * code, size_t * pc, int32_t ** sp) { @@ -104,13 +122,14 @@ process_imp_stack(uint8_t * code, size_t * pc, int32_t ** sp) switch (next_code_byte(code,pc)) { case ' ' : sign = 1; break; case '\t': sign = -1; break; - case '\n': ws_die(pc, "expected sign"); break; + default : ws_die(pc, "expected sign"); break; } /* Now, construct the number and push to TOS. */ /* I'm assuming the numbers are read MSb first. */ int32_t temp, number = 0; while ((temp = next_code_byte(code,pc)) != '\n') { + if (temp == '\v') ws_die(pc, "non-binary digit in number"); number <<= 1; if (temp == '\t') number++; } @@ -138,10 +157,13 @@ process_imp_stack(uint8_t * code, size_t * pc, int32_t ** sp) case '\n': stack_pop(sp); break; + default: + ws_die(pc, "malformed stack IMP"); + break; } } break; - case '\t': ws_die(pc, "malformed stack IMP"); break; + default: ws_die(pc, "malformed stack IMP"); break; } } @@ -166,6 +188,9 @@ process_imp_arithmetic(uint8_t * code, size_t * pc, int32_t ** sp) /* Multiplication */ stack_push(sp, stack_pop(sp)*stack_pop(sp)); break; + default: + ws_die(pc, "malformed arithmetic IMP"); + break; } } break; @@ -182,11 +207,11 @@ process_imp_arithmetic(uint8_t * code, size_t * pc, int32_t ** sp) temp = stack_pop(sp); stack_push(sp, stack_pop(sp)%temp); break; - case '\n': ws_die(pc, "malformed arithmetic IMP"); break; + default: ws_die(pc, "malformed arithmetic IMP"); break; } } break; - case '\n': ws_die(pc, "malformed arithmetic IMP"); break; + default: ws_die(pc, "malformed arithmetic IMP"); break; } } @@ -197,7 +222,6 @@ process_imp_flowcontrol(uint8_t * code, size_t * pc, int32_t ** sp, uint32_t * l switch (next_code_byte(code,pc)) { case '\n': /* Technically another LF is required but we ignore it. */ - printf("\n"); fflush(stdout); exit(EXIT_SUCCESS); case ' ': @@ -205,7 +229,10 @@ process_imp_flowcontrol(uint8_t * code, size_t * pc, int32_t ** sp, uint32_t * l switch (next_code_byte(code,pc)) { case ' ': /* Mark a location in the program. */ - labels[parse_label(code, pc)] = *pc; + if (next_code_byte(code,pc) != '\v') ws_die(pc,"expected vtab, " + "perhaps a whitespace program, rather than vvhitespace?"); + /* Jump to next instruction since labels were parsed during startup. */ + parse_label( code, pc); break; case '\t': /* Call a subroutine. */ @@ -216,6 +243,9 @@ process_imp_flowcontrol(uint8_t * code, size_t * pc, int32_t ** sp, uint32_t * l /* Jump unconditionally to a label. */ *pc = labels[parse_label(code, pc)]; break; + default: + ws_die(pc, "malformed flow control IMP"); + break; } } break; @@ -234,9 +264,15 @@ process_imp_flowcontrol(uint8_t * code, size_t * pc, int32_t ** sp, uint32_t * l /* Return from subroutine. */ *pc = *(--(*rsp)); break; + default: + ws_die(pc, "malformed flow control IMP"); + break; } } break; + default: + ws_die(pc, "malformed flow control IMP"); + break; } } @@ -246,7 +282,7 @@ process_imp_heap(uint8_t * code, size_t * pc, int32_t ** sp, int32_t ** hp) switch (next_code_byte(code,pc)) { case ' ' : /* Store to heap */ *(*hp + *((*sp)-1)) = **sp; *sp -= 2; break; case '\t': /* Retrieve from heap */ **sp = *(*hp + **sp); break; - case '\n': ws_die(pc, "malformed heap IMP"); break; + default : ws_die(pc, "malformed heap IMP"); break; } } @@ -260,7 +296,7 @@ process_imp_io(uint8_t * code, size_t * pc, int32_t ** sp, int32_t ** hp) switch (next_code_byte(code,pc)) { case ' ' : /* Output character from TOS */ printf("%c", stack_pop(sp)); break; case '\t': /* Output number from TOS */ printf("%d", stack_pop(sp)); break; - case '\n': ws_die(pc, "malformed output IMP"); break; + default : ws_die(pc, "malformed output IMP"); break; } fflush(stdout); } @@ -273,16 +309,14 @@ process_imp_io(uint8_t * code, size_t * pc, int32_t ** sp, int32_t ** hp) switch (next_code_byte(code,pc)) { case '\t': /* Input digit */ c -= '0'; /* fallthrough */ case ' ' : /* Input character */ *(*hp + *((*sp)--)) = c; break; - case '\n': ws_die(pc, "malformed input IMP"); break; + default : ws_die(pc, "malformed input IMP"); break; } } break; - case '\n': ws_die(pc, "malformed i/o IMP"); break; + default: ws_die(pc, "malformed i/o IMP"); break; } } -/* TODO: Continue cleanup here */ - int main(int argc, char ** argv) { @@ -307,25 +341,29 @@ main(int argc, char ** argv) } } if (input == NULL) { - fprintf(stderr, "ERROR: Must specify a Whitespace source file with -f flag.\n"); + fprintf(stderr, "ERROR: Must specify a VVhitespace source file with -f flag.\n"); print_usage(argv); exit(EXIT_FAILURE); } /* - * Read just the Whitespace source code into memory. + * Read just the VVhitespace source code into memory. * We will use the array indices as addresses for the virtual PC when jumping to labels. */ size_t ws_code_size = 0; uint8_t temp_byte; while (fread(&temp_byte, 1, 1, input)) { - if (temp_byte == ' ' || temp_byte == '\t' || temp_byte == '\n') ws_code_size++; + if (temp_byte == ' ' || temp_byte == '\t' || temp_byte == '\n' || temp_byte == '\v') { + ws_code_size++; + } } rewind(input); uint8_t * ws_code_space = malloc(ws_code_size); ws_code_size = 0; while (fread(&temp_byte, 1, 1, input)) { - if (temp_byte == ' ' || temp_byte == '\t' || temp_byte == '\n') ws_code_space[ws_code_size++] = temp_byte; + if (temp_byte == ' ' || temp_byte == '\t' || temp_byte == '\n' || temp_byte == '\v') { + ws_code_space[ws_code_size++] = temp_byte; + } } fclose(input); @@ -333,6 +371,7 @@ main(int argc, char ** argv) * Setup a stack and heap. * Assume a 32-bit word size. */ + // TODO: Make everything 64-bit. int32_t * hp = malloc(HEAPSIZE*4); int32_t * sp = malloc(STACKSIZE*4); @@ -340,7 +379,8 @@ main(int argc, char ** argv) * Setup the return stack and the label array. */ uint32_t * rsp = malloc(RETURNSTACKSIZE*4); - uint32_t labels[65536]; + uint32_t labels[65536] = {0}; + populate_labels(labels, ws_code_space, ws_code_size); /* * Main Loop @@ -349,9 +389,12 @@ main(int argc, char ** argv) size_t pc = 0; /* Virtual program counter. Operates in the ws_code_space[] address space. */ while (1) { if (pc >= ws_code_size) { - fprintf(stderr, "SIM_ERROR: PC Overrun\n Requested PC: %lu\n Max Address: %lu\n", pc, ws_code_size-1); + fprintf(stderr, "SIM_ERROR: PC Overrun\n Requested PC: %lu\n Max Address: %lu\n", + pc, ws_code_size-1); exit(EXIT_FAILURE); } +// TODO: Have the SIGTERM signal handler and normal term point return the value +// on TOS so I can do rudimentary automated tests. /* Decode the IMPs */ switch (ws_code_space[pc++]) { @@ -382,6 +425,7 @@ main(int argc, char ** argv) } } break; + default: ws_die(&pc, "unexpected VTab"); break; } }