Completed a rough but working C source version of brainmess
authorMichael Welch <michaelgwelch@gmail.com>
Sat, 25 Feb 2012 20:55:34 +0000 (14:55 -0600)
committerMichael Welch <michaelgwelch@gmail.com>
Sat, 25 Feb 2012 20:55:34 +0000 (14:55 -0600)
csrc/Makefile
csrc/brainmess [new file with mode: 0755]
csrc/brainmess.c [new file with mode: 0644]
csrc/execute.c [new file with mode: 0644]
csrc/execute.h [new file with mode: 0644]
csrc/prog.c [deleted file]
csrc/program.c [new file with mode: 0644]
csrc/program.h [new file with mode: 0644]
csrc/tape.c
csrc/tape.h

index 53970a4..981a74c 100644 (file)
@@ -2,7 +2,7 @@
 INC=/usr/local/include/glib-2.0 /usr/local/lib/glib-2.0/include
 IDIR=$(foreach d, $(INC), -I$d)
 CC=gcc
-CFLAGS=$(IDIR)
+CFLAGS=$(IDIR) -g
 
 ODIR=obj
 LDIR =/usr/local/lib
@@ -13,7 +13,7 @@ LIBS=-lglib-2.0
 #DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
 DEPS = tape.h
 
-_OBJ = prog.o tape.o
+_OBJ = brainmess.o tape.o execute.o program.o
 OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
 
 
diff --git a/csrc/brainmess b/csrc/brainmess
new file mode 100755 (executable)
index 0000000..8fe1c8c
Binary files /dev/null and b/csrc/brainmess differ
diff --git a/csrc/brainmess.c b/csrc/brainmess.c
new file mode 100644 (file)
index 0000000..f0e041b
--- /dev/null
@@ -0,0 +1,97 @@
+#include <stdio.h>
+#include "tape.h"
+#include "program.h"
+#include "execute.h"
+
+void putChar(gchar ch)
+{
+    putchar(ch);
+}
+
+gchar getChar()
+{
+    return getchar();
+}
+
+int main(gint argc, gchar** args) 
+{
+    Tape* t = tape_new();
+    if (argc > 1) printf("%s\n", args[1]);   
+
+    FILE* file = fopen(args[1], "r");
+    // Todo: use GString to build up and read whole file
+    int CHARS = 32000;
+    gchar* program_string = malloc(CHARS * sizeof(gchar));
+    size_t chars = fread(program_string, sizeof(gchar), CHARS, file);
+
+    if (!feof(file)) printf("Could not read the whole program");
+    fclose(file);
+
+    Program* prog = program_new(program_string);
+    while(!program_end(prog))
+    {
+        gchar instruction = program_fetch(prog);
+        execute(instruction, prog, t, getChar, putChar);
+    }
+
+
+    
+    Tape* tt = tape_new();
+    Program* p = program_new("[]");
+    execute('>', p, tt, getChar, putChar);
+    execute('+', p, tt, getChar, putChar);
+    printf("Enter a character\n");
+    execute(',', p, tt, getChar, putChar);
+    printf("Is this your character?\n");
+    execute('.', p, tt, getChar, putChar);
+    printf("%s\n", tape_to_string(tt));
+       
+    Tape* t1 = tape_new();
+    Tape* t2 = tape_new();
+
+    tape_increment(t1);
+    tape_increment(t2);
+    tape_move_forward(t1);
+    tape_move_forward(t2);
+    tape_move_backward(t1);
+    tape_move_backward(t1);
+    tape_move_backward(t2);
+    tape_move_backward(t2);
+    printf("Are equal 1? %s\n", tape_equals(t1, t2) ? "YES" : "NO");
+
+    Tape* tape = tape_new();
+    tape_increment(tape);
+    tape_increment(tape);
+    tape_increment(tape);
+    tape_move_forward(tape);
+    tape_increment(tape);
+    tape_increment(tape);
+    tape_move_backward(tape);
+    tape_move_backward(tape);
+    tape_increment(tape);
+    tape_move_forward(tape);
+    tape_move_forward(tape);
+    printf("%s\n", tape_to_string(tape)); 
+
+    Tape* tape2 = tape_new();
+    tape_move_backward(tape2);
+    tape_increment(tape2);
+    tape_move_forward(tape2);
+    tape_increment(tape2);
+    tape_increment(tape2);
+    tape_increment(tape2);
+    tape_move_forward(tape2);
+    tape_increment(tape2);
+    tape_increment(tape2);
+
+    printf("%s\n", tape_to_string(tape2));
+
+    gboolean equal = tape_equals(tape, tape2);
+    printf("Are equal? %s\n", equal ? "YES" : "NO");
+    tape_free(tape);
+    tape_free(tape2);
+
+    
+
+
+}
diff --git a/csrc/execute.c b/csrc/execute.c
new file mode 100644 (file)
index 0000000..2e128fe
--- /dev/null
@@ -0,0 +1,52 @@
+#include <stdlib.h>
+#include "tape.h"
+#include "program.h"
+#include "execute.h"
+
+void execute(gchar instruction, Program* program,
+    Tape* tape, ReadChar reader, WriteChar writer)
+{
+    switch(instruction)
+    {
+        case '>':
+            tape_move_forward(tape);
+            break;
+
+        case '<':
+            tape_move_backward(tape);
+            break;
+        
+        case '+':
+            tape_increment(tape);
+            break;
+
+        case '-':
+            tape_decrement(tape);
+            break;
+
+        case '.':
+            writer((gchar)tape_get(tape));
+            break;
+
+        case ',':
+            tape_set(tape, (gint)reader());
+            break;
+
+        case '[':
+            if (tape_get(tape) == 0) 
+            {
+                program_jump_forward(program);
+            }
+            break;
+
+        case ']':
+            if (tape_get(tape) != 0)
+            {
+                program_jump_backward(program);
+            }
+            break;
+
+        default:
+            break;
+    }
+}
diff --git a/csrc/execute.h b/csrc/execute.h
new file mode 100644 (file)
index 0000000..79ef554
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _EXECUTE_H_
+#define _EXECUTE_H_
+
+typedef gchar       (*ReadChar)     ();
+typedef void        (*WriteChar)    (gchar ch);
+
+void execute(gchar instruction, Program* program,
+        Tape* tape, ReadChar reader, WriteChar writer);
+
+#endif
diff --git a/csrc/prog.c b/csrc/prog.c
deleted file mode 100644 (file)
index f409d1f..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <stdio.h>
-#include "tape.h"
-int main() {
-    Tape* tape = tape_new();
-    tape_increment(tape);
-    tape_increment(tape);
-    tape_increment(tape);
-    tape_move_forward(tape);
-    tape_increment(tape);
-    tape_increment(tape);
-    tape_move_backward(tape);
-    tape_move_backward(tape);
-    tape_increment(tape);
-    printf("%s\n", tape_to_string(tape)); 
-}
diff --git a/csrc/program.c b/csrc/program.c
new file mode 100644 (file)
index 0000000..6de0731
--- /dev/null
@@ -0,0 +1,73 @@
+#include <stdlib.h>
+#include <string.h>
+#include "program.h"
+
+struct _Program 
+{
+    gchar* instructions;
+    size_t length;
+    int index;
+};
+
+Program* program_new(const gchar* prog)
+{
+    // TODO: Expect prog to be null terminated. What is
+    // best practice for handling?
+
+    Program* program;
+    program = malloc(sizeof(*program));
+
+    // TODO: use a glib function later.
+    // Don't leave room for NULL.
+    program->length = strlen(prog);
+    program->instructions = malloc(program->length * sizeof(gchar));
+    strncpy(program->instructions, prog, program->length);
+    program->index = 0;
+
+    return program;
+
+}
+
+void program_free(Program* prog)
+{
+    free(prog->instructions);
+    free(prog);
+}
+
+gboolean program_end(const Program* prog)
+{
+    return prog->index >= prog->length;
+}
+
+gchar program_fetch(Program* prog)
+{
+    gchar instruction = prog->instructions[prog->index];
+    prog->index++;
+    return instruction;
+}
+
+void program_jump_forward(Program* prog)
+{
+    int nestLevel = 1;
+    while(nestLevel > 0)
+    {
+        gchar current = prog->instructions[prog->index];
+        if (current == '[') nestLevel++;
+        else if (current == ']') nestLevel--;
+        prog->index++;
+    }
+}
+
+void program_jump_backward(Program* prog)
+{
+    prog->index -= 2;
+    int nestLevel = 1;
+    while (nestLevel > 0)
+    {
+        gchar current = prog->instructions[prog->index];
+        if (current == '[') nestLevel--;
+        else if (current == ']') nestLevel++;
+        prog->index--;
+    }
+    prog->index++;
+}
diff --git a/csrc/program.h b/csrc/program.h
new file mode 100644 (file)
index 0000000..393002a
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _PROGRAM_H_
+#define _PROGRAM_H_
+#include <glib.h>
+
+typedef struct _Program Program;
+
+Program* program_new(const gchar* prog);
+void program_free(Program* prog);
+void program_jump_forward(Program* prog);
+void program_jump_backward(Program* prog);
+gboolean program_end(const Program* prog);
+gchar program_fetch(Program* prog);
+
+
+
+#endif
index 501c473..87ba606 100644 (file)
@@ -3,6 +3,29 @@
 
 const gpointer GPTR_ZERO = GINT_TO_POINTER(0);
 
+// NOTES:
+// What do you do in a C program if an argument is NULL
+// and that isn't expected?
+
+struct _Tape 
+{
+    GList *currentCell;
+};
+
+int index_of_node_in_list(GList *node)
+{
+    int index = 0;
+    GList *current = node;
+
+    while(current != NULL)
+    {
+        current = g_list_previous(current);
+        index++;
+    }
+
+    return index;
+}
+
 Tape* tape_new()
 {
     Tape* newTape;
@@ -11,6 +34,12 @@ Tape* tape_new()
     return newTape;
 }
 
+void tape_free(Tape *tape)
+{
+    g_list_free(g_list_first(tape->currentCell));
+    free(tape);
+}
+
 GList* nextCell(GList *list)
 {
     GList* next = g_list_next(list);
@@ -37,7 +66,7 @@ void tape_set(Tape *tape, int value)
     tape->currentCell->data = GINT_TO_POINTER(value);
 }
 
-int tape_get(Tape *tape)
+int tape_get(const Tape *tape)
 {
     return GPOINTER_TO_INT(tape->currentCell->data);
 }
@@ -68,7 +97,7 @@ void append_next(gpointer data, gpointer string)
 }
 
 const gboolean RETURN_BUFFER = FALSE;
-gchar* tape_to_string(Tape* tape)
+gchar* tape_to_string(const Tape* tape)
 {
     GString *result = g_string_new("Tape [");
     GList *current = g_list_first(tape->currentCell);
@@ -77,3 +106,35 @@ gchar* tape_to_string(Tape* tape)
     g_string_append(result, "]");
     return g_string_free(result, RETURN_BUFFER);
 }
+
+gboolean tape_equals(const Tape *tape1, const Tape *tape2)
+{
+    GList* iter1 = g_list_first(tape1->currentCell);
+    GList* iter2 = g_list_first(tape2->currentCell);
+
+    gboolean equal = TRUE;
+    while(iter1 != NULL && iter2 != NULL)
+    {
+        if (iter1->data != iter2->data)
+        {
+            equal = FALSE;
+            break;
+        }
+        iter1 = g_list_next(iter1);
+        iter2 = g_list_next(iter2);
+    }
+
+    if (equal)
+    {
+        equal = iter1 == iter2;
+    }
+
+    if (equal)
+    {
+        gint index1 = index_of_node_in_list(tape1->currentCell);
+        gint index2 = index_of_node_in_list(tape2->currentCell);
+        equal = (index1 == index2);
+    }
+
+    return equal;
+}
index 6348905..a06ffdc 100644 (file)
@@ -5,18 +5,17 @@
 
 typedef struct _Tape Tape;
 
-struct _Tape {
-   GList *currentCell;
-};
 
 Tape* tape_new();
-gchar* tape_to_string(Tape *tape);
+void tape_free(Tape *tape);
+gchar* tape_to_string(const Tape *tape);
 void tape_increment(Tape *tape);
 void tape_decrement(Tape *tape);
 void tape_move_forward(Tape *tape);
 void tape_move_backward(Tape *tape);
 void tape_set(Tape *tape, int value);
-int tape_get(Tape *tape);
+gint tape_get(const Tape *tape);
+gboolean tape_equals(const Tape *tape1, const Tape *tape2);
 
 
 #endif