Enigma-2D

Enigma-2D is the name of a 2D programming language made by User:Alegend, on February 14, 2010. It is a mix of Minimal-2D, and BF. It only has 12 commands:
== Opcodes ==
Opcode	Action
< 	Move the data pointer left
> 	Move the data pointer right
+ 	Add to the value in the data pointer
- 	Subtract from the value in the data pointer
. 	Outputs the value in the data pointer
, 	Asks for input from the user
U 	Tells the program to switch to the up direction of processing instructions
D 	Tells the program to switch to the down direction of processing instructions
L 	Tells the program to switch to the left direction of processing instructions
R 	Tells the program to switch to the right direction of processing instructions
[ 	Jump past the matching ] if the cell under the data pointer is 0
] 	Jump back to the matching [ if the cell under the data pointer is nonzero
The program, when it starts, automatically starts processing directions to the right.
==Implementations==
This language has been implemented in C, with some unspecified details assumed:
* Data elements are ints.
* "End of data" from input is represented as -1.
* Invalid characters must not be reached by the interpreter.
* Spaces are considered a valid no-op.
* The program ends when the instruction processor falls off the edge of the 2D field.
 #include <stdio.h>
 #include <stdlib.h>
 
 // Counted string
 typedef struct {
 char *data;
 size_t len;
 } str;
 
 // Counted array of counted strings
 typedef struct {
 str *arr;
 size_t len;
 } arr_strs;
 
 arr_strs make_jagged_array(char *restrict in, size_t len) {
 char *linestart = in;
 size_t num_lines = 1;
 
 for (size_t i = 0; i < len; i++) {
 if (in[i] == '\r' || in[i] == '\n') {
 num_lines++;
 if (in[i] == '\r' && i + 1 < len && in[i + 1] == '\n') {
 i++;
 }
 }
 }
 
 str *jagg = malloc(sizeof(str) * num_lines);
 int line = 0;
 
 for (size_t i = 0; i < len; i++) {
 char c = *in;
 if (c == '\r' || c == '\n') {
 jagg[line++] = (str) {.data = linestart, .len = in - linestart};
 if (c == '\r' && i + 1 < len && *(in + 1) == '\n') { in++; i++; }
 linestart = in + 1;
 }
 in++;
 }
 jagg[line++] = (str) {.data = linestart, .len = in - linestart};
 
 return (arr_strs) {.arr = jagg, .len = line};
 }
 
 typedef struct {
 int row, col, dir_row, dir_col;
 int data_pointer, data_allocated;
 int *data;
 arr_strs script;
 } interpreter_state;
 
 void interpreter_error(char *error, interpreter_state *restrict s) {
 char *direction = "???";
 if (s->dir_row == 1 && s->dir_col == 0) direction = "Down";
 else if (s->dir_row == -1 && s->dir_col == 0) direction = "Up";
 else if (s->dir_row == 0 && s->dir_col == 1) direction = "Right";
 else if (s->dir_row == 0 && s->dir_col == -1) direction = "Left";
 
 fprintf(stderr, "\n---Error---\n%s\nLine %d char %d\nDirection: %s\nData pointer: %d\nData cells (hex):\n", error, s->row, s->col, direction, s->data_pointer);
 for (int i = 0; i < s->data_allocated; i++) {
 fprintf(stderr, "\t%08X: %08X\n", i, s->data[i]);
 }
 }
 
 int ensure_data(interpreter_state *restrict s) {
 if (s->data_pointer < 0) {
 interpreter_error("Tried to write to a negative address", s);
 return 0;
 }
 if (s->data_pointer >= s->data_allocated) {
 int orig_allocated = s->data_allocated;
 s->data_allocated = s->data_pointer + 1;
 s->data = realloc(s->data, s->data_allocated * sizeof(*s->data));
 if (s->data == NULL) {
 interpreter_error("Out of memory", s);
 return 0;
 }
 while (orig_allocated < s->data_allocated) {
 s->data[orig_allocated++] = 0;
 }
 }
 return 1;
 }
 
 int within_bounds(interpreter_state *restrict s) {
 if (s->row < 0 || s->col < 0) return 0;
 if (s->row >= s->script.len) return 0;
 if (s->dir_row == 0 && s->col >= s->script.arr[s->row].len) return 0;
 return 1;
 }
 
 int interpret_once(interpreter_state *restrict s) {
 switch (s->script.arr[s->row].data[s->col]) {
 case '<':
 s->data_pointer--;
 break;
 case '>':
 s->data_pointer++;
 break;
 case '+':
 if (!ensure_data(s)) return 0;
 s->data[s->data_pointer]++;
 break;
 case '-':
 if (!ensure_data(s)) return 0;
 s->data[s->data_pointer]--;
 break;
 case '.':
 if (!ensure_data(s)) return 0;
 putchar(s->data[s->data_pointer]);
 break;
 case ',':
 if (!ensure_data(s)) return 0;
 s->data[s->data_pointer] = getchar();
 break;
 case 'U':
 s->dir_row = -1;
 s->dir_col = 0;
 break;
 case 'D':
 s->dir_row = 1;
 s->dir_col = 0;
 break;
 case 'L':
 s->dir_row = 0;
 s->dir_col = -1;
 break;
 case 'R':
 s->dir_row = 0;
 s->dir_col = 1;
 break;
 case '[':
 if (!ensure_data(s)) return 0;
 if (s->data[s->data_pointer] == 0) {
 int num_brackets = 1;
 do {
 s->row += s->dir_row;
 s->col += s->dir_col;
 if (!within_bounds(s)) break;
 
 char c = s->script.arr[s->row].data[s->col];
 if (c == '[') num_brackets++;
 else if (c == ']') num_brackets--;
 } while (num_brackets > 0);
 
 if (!within_bounds(s)) {
 interpreter_error("Fell off the end of the script looking for a \"]\"", s);
 return 0;
 }
 }
 break;
 case ']':
 if (!ensure_data(s)) return 0;
 if (s->data[s->data_pointer] != 0) {
 int num_brackets = 1;
 do {
 s->row -= s->dir_row;
 s->col -= s->dir_col;
 if (!within_bounds(s)) break;
 
 char c = s->script.arr[s->row].data[s->col];
 if (c == ']') num_brackets++;
 else if (c == '[') num_brackets--;
 } while (num_brackets > 0);
 
 if (!within_bounds(s)) {
 interpreter_error("Fell off the end of the script looking for a \"[\"", s);
 return 0;
 }
 }
 break;
 case ' ':
 break;
 default:
 interpreter_error("Invalid opcode", s);
 return 0;
 }
 return 1;
 }
 
 void interpret(arr_strs script) {
 interpreter_state s = {.dir_col = 1, .script = script};
 while (within_bounds(&s)) {
 if (s.col < s.script.arr[s.row].len)
 if (!interpret_once(&s))
 break;
 s.row += s.dir_row;
 s.col += s.dir_col;
 }
 
 if (s.data != NULL) free(s.data);
 }
 
 int main(int argc, char **argv) {
 if (argc < 2) {
 puts("At least give me some files to execute.");
 return 0;
 }
 
 for (int i = 1; i < argc; i++) {
 FILE *f = fopen(argv[i], "rb");
 if (!f) {
 fprintf(stderr, "Could not open the script \"%s\": ", argv[i]);
 perror(NULL);
 continue;
 }
 
 fseek(f, 0, SEEK_END);
 long f_len = ftell(f);
 fseek(f, 0, SEEK_SET);
 
 char *script_raw = malloc(f_len);
 fread(script_raw, 1, f_len, f);
 
 fclose(f);
 
 arr_strs script = make_jagged_array(script_raw, f_len);
 interpret(script);
 free(script.arr);
 free(script_raw);
 }
 }
Category:Languages
Category:2010
Category:Two-dimensional languages
Category:Implemented
Category:Turing complete