4Head/AuthorImplementation.c
Jump to navigation
Jump to search
#include <assert.h> #include <inttypes.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #define cell int16_t #define MEM_X 100 #define MEM_Y 100 int is_digit(char x) { return '0' <= x && x <= '9'; } void print_2d_array(cell *array, size_t width, size_t height, size_t x, size_t y) { for (size_t yi = 0; yi < height; ++yi) { for (size_t xi = 0; xi < width; ++xi) { size_t i = width*yi + xi; if (x == xi && y == yi) { printf(">%2d<", array[i]); } else { printf(" %2d ", array[i]); } } printf("\n"); } } void interpret_program(const char *program, size_t program_length, int enable_debug) { const size_t width = MEM_X, height = MEM_Y; cell memory[MEM_Y][MEM_X] = {0}; size_t x = 0, y = 0; size_t amount = 1; cell hold = 0; size_t i = 0; while (i < program_length) { #if 0 printf("i=%3lld,x=%2lld,y=%2lld\n", i, x, y); #endif switch(program[i]) { case '+': // Increment hold += amount; amount = 1; i++; break; case '-': // Decrement hold -= amount; amount = 1; i++; break; case '<': // Move left if (amount >= x) { x = 0; } else { x -= amount; } amount = 1; i++; break; case '>': // Move right if (x + amount > width-1) { x = width-1; } else { x += amount; } amount = 1; i++; break; case '^': // Move up if (amount >= y) { y = 0; } else { y -= amount; } amount = 1; i++; break; case 'v': // Move down if (y + amount > height-1) { y = height-1; } else { y += amount; } amount = 1; i++; break; case '@': // Fetch hold = memory[y][x]; amount = 1; i++; break; case '!': // Store memory[y][x] = hold; amount = 1; i++; break; case '%': // Swap { cell t = memory[y][x]; memory[y][x] = hold; hold = t; amount = 1; i++; } break; case '[': // Jump past matching bracket if current cell is 0 if (hold == 0) { int level = 1; int original_i = i; // inefficient while loop to find the matching bracket while (level != 0 && i < program_length) { i++; if (program[i] == '[') { level++; } else if (program[i] == ']') { level--; } } if (level != 0) { printf("ERROR: unmatched opening bracket '[' at index %d", original_i); exit(1); } } i++; amount = 1; break; case ']': // Jump back to the matching bracket if current cell is not 0 if (hold != 0) { int level = 1; int original_i = i; // inefficient while loop to find the matching bracket while (level != 0 && i < program_length) { i--; if (program[i] == ']') { level++; } else if (program[i] == '[') { level--; } } if (level != 0) { printf("ERROR: unmatched opening bracket ']' at index %d", original_i); exit(1); } } i++; amount = 1; break; case '?': // Get a character of input hold = getchar(); i++; amount = 1; break; case '.': // Set a character of output putchar(hold); i++; amount = 1; break; case '#': // Debugger if (enable_debug) { printf("\n"); print_2d_array((cell*) memory, width, height, x, y); amount = 1; } i++; break; default: // Try to read a number and ignore any other characters if (is_digit(program[i])) { // Start of a number, so set the amount to it size_t n = 0; while (is_digit(program[i])) { n = (n*10) + (program[i] - '0'); i++; } if (n) { amount = n; } } else { // Ignore non-number i++; } break; } } }