X-Git-Url: http://git.subgeniuskitty.com/vvhitespace/.git/blobdiff_plain/eea0db3fe145a963cc85df6e5785c9bcc54b63ab..e5d2b9bf5614e1674ebe47db7b7f1076e85c1bd5:/vv_interpreter.c diff --git a/vv_interpreter.c b/vv_interpreter.c index 337fd61..cf5cdef 100644 --- a/vv_interpreter.c +++ b/vv_interpreter.c @@ -15,9 +15,9 @@ #define VERSION 1 -#define HEAPSIZE 1024 /* Size of heap in words */ -#define DATASTACKSIZE 1024 /* Size of stack in words */ -#define RETURNSTACKSIZE 1024 /* Max subroutine call depth */ +#define HEAPSIZE 65536 /* Size of heap in words */ +#define DATASTACKSIZE 65536 /* Size of stack in words */ +#define RETURNSTACKSIZE 65536 /* Max subroutine call depth */ void print_usage(char ** argv) @@ -118,10 +118,18 @@ parse_label(uint8_t * code, size_t * pc) uint8_t c; while ((c = code[(*pc)++]) != '\n') { label = label << 1; - if (c == ' ') label++; + if (c == '\t') label++; + } + return label; +} + +uint16_t +check_label(size_t * labels, uint16_t label, size_t * pc) +{ + if (!labels[label]) { + fprintf(stderr, "Trying to process label 0x%X.\n", label); + ws_die(pc, "uninitialized label (forgot an include?)"); } - // TODO: Where should I handle attempts to access an unitialized label? - // For now, leave it undefined in a nasal demon sense. return label; } @@ -130,11 +138,10 @@ populate_labels(size_t * labels, uint8_t * code, size_t code_size) { size_t cp = 0; while (cp <= code_size) { - if (code[cp] == '\v') { + if (code[cp++] == '\v') { uint16_t temp_label = parse_label(code, &cp); labels[temp_label] = cp; } - cp++; } } @@ -155,14 +162,26 @@ process_imp_stack(uint8_t * code, size_t * pc, int64_t ** sp) /* Now, construct the number and push to TOS. */ /* I'm assuming the numbers are read MSb first. */ - int64_t number = 0; + uint64_t number = 0; /* Unsigned to accomodate magnitude of most negative number. */ uint8_t temp; 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++; } - stack_push(sp, number*sign); + /* Without temporarily casting to something >64-bit, the most negative */ + /* number will overflow when performing 'number*sign'. Instead, we */ + /* pick off the most negative number as a special case. */ + if (number == (1ULL << 63) && sign == -1) { + /* C parses negative integer literals first as signed positive */ + /* integer literals, then applying a unary negation operator. */ + /* Thus, the most negative value is unreachable directly. */ + int64_t number_temp = -9223372036854775807LL; /* First store -((2^63)-1) */ + number_temp--; /* Now turn it into -(2^63) */ + stack_push(sp, number_temp); + } else { + stack_push(sp, number*sign); + } } break; case '\n': @@ -234,7 +253,7 @@ process_imp_arithmetic(uint8_t * code, size_t * pc, int64_t ** sp) case '\t': /* Modulo */ temp = stack_pop(sp); - stack_push(sp, stack_pop(sp)%temp); + stack_push(sp, llabs(stack_pop(sp) % llabs(temp))); break; default: ws_die(pc, "malformed arithmetic IMP"); break; } @@ -248,6 +267,7 @@ void process_imp_flowcontrol(uint8_t * code, size_t * pc, int64_t ** sp, size_t * labels, size_t ** rsp) { + size_t temp_pc; switch (next_code_byte(code,pc)) { case '\n': /* Technically another LF is required but we ignore it. */ @@ -266,15 +286,13 @@ process_imp_flowcontrol(uint8_t * code, size_t * pc, int64_t ** sp, size_t * lab break; case '\t': /* Call a subroutine. */ - { - size_t temp_pc = labels[parse_label(code, pc)]; - *((*rsp)++) = *pc; - *pc = temp_pc; - } + temp_pc = labels[check_label(labels, parse_label(code, pc), pc)]; + *((*rsp)++) = *pc; + *pc = temp_pc; break; case '\n': /* Jump unconditionally to a label. */ - *pc = labels[parse_label(code, pc)]; + *pc = labels[check_label(labels, parse_label(code, pc), pc)]; break; default: ws_die(pc, "malformed flow control IMP"); @@ -287,11 +305,13 @@ process_imp_flowcontrol(uint8_t * code, size_t * pc, int64_t ** sp, size_t * lab switch (next_code_byte(code,pc)) { case ' ': /* Jump to a label if TOS == 0 */ - if (stack_pop(sp) == 0) *pc = labels[parse_label(code, pc)]; + temp_pc = labels[check_label(labels, parse_label(code, pc), pc)]; + if (stack_pop(sp) == 0) *pc = temp_pc; break; case '\t': /* Jump to a label if TOS < 0. */ - if (stack_pop(sp) < 0) *pc = labels[parse_label(code, pc)]; + temp_pc = labels[check_label(labels, parse_label(code, pc), pc)]; + if (stack_pop(sp) < 0) *pc = temp_pc; break; case '\n': /* Return from subroutine. */ @@ -435,8 +455,8 @@ main(int argc, char ** argv) 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); - exit(EXIT_FAILURE); unset_terminal_mode(); + exit(EXIT_FAILURE); } /* Decode the IMPs */