Get all examples compiling, though output is not correct
[fur] / templates / program2.c
index f307b85..f51cdbf 100644 (file)
@@ -12,7 +12,9 @@ enum Type {
   BUILTIN,
   CLOSURE,
   INTEGER,
-  STRING
+  LIST,
+  STRING,
+  SYMBOL
 };
 
 enum Builtin;
@@ -23,8 +25,12 @@ enum Builtin {
   PRINT
 };
 
+struct Object;
+typedef struct Object Object;
 struct Environment;
 typedef struct Environment Environment;
+struct Thread;
+typedef struct Thread Thread;
 
 struct Closure;
 typedef struct Closure Closure;
@@ -33,23 +39,31 @@ struct Closure {
   size_t entry;
 };
 
+struct List;
+typedef struct List List;
+
 union Value;
 typedef union Value Value;
 union Value {
   Builtin builtin;
-  Closure closure;
   bool boolean;
-  char* string;
+  Closure closure;
   int32_t integer;
+  List* list;
+  char* string;
+  char* symbol;
 };
 
-struct Object;
-typedef struct Object Object;
 struct Object {
   Type type;
   Value value;
 };
 
+struct List {
+  Object head;
+  List* tail;
+};
+
 #define BUILTIN_NIL (Object) { BUILTIN, (Value)(Builtin)NIL }
 
 void Object_deinitialize(Object* self) {
@@ -59,39 +73,35 @@ void Object_deinitialize(Object* self) {
 {% include "stack.c" %}
 {% include "frame.c" %}
 
-struct Thread;
-typedef struct Thread Thread;
 struct Thread {
-  Environment* environment;
+  Frame frame;
   Stack stack;
-  size_t programCounter;
 };
 
 void Thread_initialize(Thread* self, size_t programCounter) {
-  self->environment = Environment_construct();
+  Frame_initialize(&(self->frame), Environment_construct(NULL), NULL, programCounter);
   Stack_initialize(&(self->stack));
-  self->programCounter = programCounter;
 }
 
 void Thread_deinitialize(Thread* self) {
-  Environment_destruct(self->environment);
+  Frame_deinitialize(&(self->frame));
   Stack_deinitialize(&(self->stack));
 }
 
 Environment* Thread_getEnvironment(Thread* self) {
-  return self->environment;
+  return self->frame.environment;
 }
 
 void Thread_setProgramCounter(Thread* self, size_t programCounter) {
-  self->programCounter = programCounter;
+  self->frame.programCounter = programCounter;
 }
 
 void Thread_incrementProgramCounter(Thread* self) {
-  self->programCounter++;
+  self->frame.programCounter++;
 }
 
 size_t Thread_getProgramCounter(Thread* self) {
-  return self->programCounter;
+  return self->frame.programCounter;
 }
 
 union Argument;
@@ -101,6 +111,7 @@ union Argument {
   void* pointer;
   char* string;
   int32_t integer;
+  char* symbol;
 };
 
 void callBuiltinPow(Thread* thread, size_t argumentCount) {
@@ -179,7 +190,14 @@ void callBuiltin(Thread* thread, Builtin b, size_t argumentCount) {
 void callClosure(Thread* thread, Closure closure, size_t argumentCount) {
   assert(argumentCount == 0);
 
-
+  Frame* returnFrame = malloc(sizeof(Frame));
+  *returnFrame = thread->frame;
+  Frame_initialize(
+    &(thread->frame),
+    Environment_construct(Environment_reference(closure.environment)),
+    returnFrame,
+    closure.entry - 1 // We will increment the frame immediately after this
+  );
 }
 
 void inst_call(Thread* thread, Argument argument) {
@@ -201,6 +219,29 @@ void inst_call(Thread* thread, Argument argument) {
   }
 }
 
+void inst_concat(Thread* thread, Argument argument) {
+  assert(!Stack_isEmpty(&(thread->stack)));
+  Object left = Stack_pop(&(thread->stack));
+  assert(!Stack_isEmpty(&(thread->stack)));
+  Object right = Stack_pop(&(thread->stack));
+
+  assert(left.type == STRING);
+  assert(right.type == STRING);
+
+  char* resultString = malloc(strlen(left.value.string) + strlen(right.value.string) + 1);
+  resultString[0] = '\0';
+
+  strcat(resultString, left.value.string);
+  strcat(resultString, right.value.string);
+
+  Object resultObject = (Object) {
+    STRING,
+    (Value)resultString
+  };
+
+  Stack_push(&(thread->stack), resultObject);
+}
+
 {% with name='add', operation='+' %}
   {% include "arithmetic_instruction.c" %}
 {% endwith %}
@@ -227,6 +268,27 @@ void inst_end(Thread* thread, Argument argument) {
   {% include "comparison_instruction.c" %}
 {% endwith %}
 
+void inst_get(Thread* thread, Argument argument) {
+  assert(!Stack_isEmpty(&(thread->stack)));
+  Object listObject = Stack_pop(&(thread->stack));
+  assert(listObject.type == LIST);
+  List* list = listObject.value.list;
+
+  assert(!Stack_isEmpty(&(thread->stack)));
+  Object indexObject = Stack_pop(&(thread->stack));
+  assert(indexObject.type == INTEGER);
+  int32_t index = indexObject.value.integer;
+
+  while(index > 0) {
+    assert(list != NULL);
+    list = list->tail;
+    index--;
+  }
+
+  assert(list != NULL);
+  Stack_push(&(thread->stack), list->head);
+}
+
 {% with name='gt', operation='>' %}
   {% include "comparison_instruction.c" %}
 {% endwith %}
@@ -253,6 +315,25 @@ void inst_jump_if_false(Thread* thread, Argument argument) {
   }
 }
 
+void inst_list(Thread* thread, Argument argument) {
+  Object result;
+  result.type = LIST;
+  result.value.list = NULL;
+
+  while(argument.integer > 0) {
+    assert(!Stack_isEmpty(&(thread->stack)));
+    Object item = Stack_pop(&(thread->stack));
+
+    List* node = malloc(sizeof(List));
+    node->head = item;
+    node->tail = result.value.list;
+
+    result.value.list = node;
+  }
+
+  Stack_push(&(thread->stack), result);
+}
+
 {% with name='lt', operation='<' %}
   {% include "comparison_instruction.c" %}
 {% endwith %}
@@ -345,11 +426,34 @@ void inst_push_string(Thread* thread, Argument argument) {
   Stack_push(&(thread->stack), result);
 }
 
+void inst_push_symbol(Thread* thread, Argument argument) {
+  // TODO Store symbols in a symbol table so they can be looked up by reference
+  // without string comparison
+  Object result;
+  result.type = SYMBOL;
+  result.value.symbol = argument.symbol;
+}
+
 {% with name='sub', operation='-' %}
   {% include "arithmetic_instruction.c" %}
 {% endwith %}
 
 void inst_return(Thread* thread, Argument argument) {
+  Frame* returnFrame = thread->frame.returnFrame;
+
+  Frame_deinitialize(&(thread->frame));
+
+  Frame_initialize(
+    &(thread->frame),
+    returnFrame->environment,
+    returnFrame->returnFrame,
+    returnFrame->programCounter
+  );
+
+  free(returnFrame);
+}
+
+void inst_structure(Thread* thread, Argument argument) {
   assert(false);
 }