Implement and/or, introducing jumps and labels
[fur] / templates / program2.c
index 8abe2a2..180a4c7 100644 (file)
@@ -8,6 +8,7 @@
 enum Type;
 typedef enum Type Type;
 enum Type {
+  BOOLEAN,
   BUILTIN,
   INTEGER,
   STRING
@@ -17,6 +18,7 @@ enum Builtin;
 typedef enum Builtin Builtin;
 enum Builtin {
   NIL,
+  POW,
   PRINT
 };
 
@@ -24,6 +26,7 @@ union Value;
 typedef union Value Value;
 union Value {
   Builtin builtin;
+  bool boolean;
   char* string;
   int32_t integer;
 };
@@ -71,13 +74,38 @@ union Argument {
   int32_t integer;
 };
 
-void call(struct Thread* thread, const union Argument argument) {
+void call(struct Thread* thread, Argument argument) {
   assert(!Stack_isEmpty(&(thread->stack)));
   Object f = Stack_pop(&(thread->stack));
+  size_t argumentCount = argument.label;
 
   switch(f.type) {
     case BUILTIN:
       switch(f.value.builtin) {
+        case POW:
+          {
+            assert(argumentCount == 2);
+            assert(!Stack_isEmpty(&(thread->stack)));
+            Object exponent = Stack_pop(&(thread->stack));
+            assert(exponent.type == INTEGER);
+            assert(exponent.value.integer >= 0);
+
+            assert(!Stack_isEmpty(&(thread->stack)));
+            Object base = Stack_pop(&(thread->stack));
+            assert(base.type == INTEGER);
+
+            Object result;
+            result.type = INTEGER;
+            result.value.integer = 1;
+
+            while(exponent.value.integer > 0) {
+              result.value.integer *= base.value.integer;
+              exponent.value.integer--;
+            }
+
+            Stack_push(&(thread->stack), result);
+          }
+          break;
         case PRINT:
           {
             // TODO Handle multiple arguments
@@ -85,6 +113,11 @@ void call(struct Thread* thread, const union Argument argument) {
             Object arg = Stack_pop(&(thread->stack));
 
             switch(arg.type) {
+              case BOOLEAN:
+                if(arg.value.boolean) printf("true");
+                else printf("false");
+                break;
+
               case INTEGER:
                 printf("%i", arg.value.integer);
                 break;
@@ -116,19 +149,53 @@ void call(struct Thread* thread, const union Argument argument) {
 {% endwith %}
 
 
-void drop(struct Thread* thread, const union Argument argument) {
+void drop(struct Thread* thread, Argument argument) {
   assert(!Stack_isEmpty(&(thread->stack)));
   Object result = Stack_pop(&(thread->stack));
   Object_deinitialize(&result);
 }
 
-void end(struct Thread* thread, const union Argument argument) {
+void end(struct Thread* thread, Argument argument) {
 }
 
+{% with name='eq', operation='==' %}
+  {% include "comparison_instruction.c" %}
+{% endwith %}
+
+{% with name='gt', operation='>' %}
+  {% include "comparison_instruction.c" %}
+{% endwith %}
+
+{% with name='gte', operation='>=' %}
+  {% include "comparison_instruction.c" %}
+{% endwith %}
+
 {% with name='idiv', operation='/' %}
   {% include "arithmetic_instruction.c" %}
 {% endwith %}
 
+void jump(Thread* thread, Argument argument) {
+  thread->program_counter = argument.label - 1; // We will increment before running
+}
+
+void jump_if_false(Thread* thread, Argument argument) {
+  assert(!Stack_isEmpty(&(thread->stack)));
+  Object result = Stack_pop(&(thread->stack));
+  assert(result.type == BOOLEAN);
+
+  if(!(result.value.boolean)) {
+    jump(thread, argument);
+  }
+}
+
+{% with name='lt', operation='<' %}
+  {% include "comparison_instruction.c" %}
+{% endwith %}
+
+{% with name='lte', operation='<=' %}
+  {% include "comparison_instruction.c" %}
+{% endwith %}
+
 {% with name='mod', operation='%' %}
   {% include "arithmetic_instruction.c" %}
 {% endwith %}
@@ -137,7 +204,21 @@ void end(struct Thread* thread, const union Argument argument) {
   {% include "arithmetic_instruction.c" %}
 {% endwith %}
 
-void pop(struct Thread* thread, const union Argument argument) {
+{% with name='neq', operation='!=' %}
+  {% include "comparison_instruction.c" %}
+{% endwith %}
+
+void neg(Thread* thread, Argument argument) {
+  assert(!Stack_isEmpty(&(thread->stack)));
+  Object result = Stack_pop(&(thread->stack));
+  assert(result.type == INTEGER);
+
+  result.value.integer = -(result.value.integer);
+
+  Stack_push(&(thread->stack), result);
+}
+
+void pop(struct Thread* thread, Argument argument) {
   char* argumentString = argument.string;
 
   assert(!Stack_isEmpty(&(thread->stack)));
@@ -145,19 +226,31 @@ void pop(struct Thread* thread, const union Argument argument) {
 
   if(strcmp(argumentString, "print") == 0) {
     assert(false);
+  } else if(strcmp(argumentString, "pow") == 0) {
+    assert(false);
   }
 
+
   Environment_set(thread->environment, argumentString, result);
 }
 
-void push(struct Thread* thread, const union Argument argument) {
+void push(struct Thread* thread, Argument argument) {
   char* argumentString = argument.string;
 
-  if(strcmp(argumentString, "print") == 0) {
+  if(strcmp(argumentString, "false") == 0) {
+    Stack_push(&(thread->stack), (Object){ BOOLEAN, false });
+  }else if(strcmp(argumentString, "pow") == 0) {
+    Object result;
+    result.type = BUILTIN;
+    result.value.builtin = POW;
+    Stack_push(&(thread->stack), result);
+  } else if(strcmp(argumentString, "print") == 0) {
     Object result;
     result.type = BUILTIN;
     result.value.builtin = PRINT;
     Stack_push(&(thread->stack), result);
+  } else if(strcmp(argumentString, "true") == 0) {
+    Stack_push(&(thread->stack), (Object){ BOOLEAN, true });
   } else {
     Environment_get_Result result = Environment_get(thread->environment, argumentString);
     if(!result.found) {
@@ -168,7 +261,7 @@ void push(struct Thread* thread, const union Argument argument) {
   }
 }
 
-void push_integer(struct Thread* thread, const union Argument argument) {
+void push_integer(struct Thread* thread, Argument argument) {
   Object result;
   result.type = INTEGER;
   result.value.integer = argument.integer;
@@ -176,7 +269,7 @@ void push_integer(struct Thread* thread, const union Argument argument) {
   Stack_push(&(thread->stack), result);
 }
 
-void push_string(struct Thread* thread, const union Argument argument) {
+void push_string(struct Thread* thread, Argument argument) {
   Object result;
   result.type = STRING;
   result.value.string = argument.string;
@@ -191,7 +284,7 @@ void push_string(struct Thread* thread, const union Argument argument) {
 struct Instruction;
 typedef const struct Instruction Instruction;
 struct Instruction {
-  void (*instruction)(struct Thread*,const union Argument);
+  void (*instruction)(struct Thread*,Argument);
   Argument argument;
 };
 
@@ -207,7 +300,7 @@ const Instruction program[] = {
 
 int main() {
   Thread thread;
-  Thread_initialize(&thread, 0);
+  Thread_initialize(&thread, LABEL___main__);
 
   for(; program[thread.program_counter].instruction != end; thread.program_counter++) {
     program[thread.program_counter].instruction(