Get all examples compiling, though output is not correct
authorDavid Kerkeslager <kerkeslager@gmail.com>
Sun, 3 Jan 2021 18:27:10 +0000 (13:27 -0500)
committerDavid Kerkeslager <kerkeslager@gmail.com>
Sun, 3 Jan 2021 18:27:10 +0000 (13:27 -0500)
c_generation.py
crossplatform_ir_generation.py
templates/frame.c [new file with mode: 0644]
templates/program2.c

index 78a80b1..0e66abb 100644 (file)
@@ -41,7 +41,7 @@ def generate_size_t_argument(argument):
     return '(size_t){}'.format(argument)
 
 def generate_string_argument(argument):
-    return argument
+    return argument[0] + ''.join('\\"' if ch == '"' else ch for ch in argument[1:-1]) + argument[-1]
 
 def generate_symbol_argument(argument):
     assert argument.startswith('sym(') and argument.endswith(')')
@@ -53,14 +53,17 @@ def generate_argument(instruction):
             'add': generate_null_argument_from(2),
             'call': generate_size_t_argument,
             'close': generate_label_argument,
+            'concat': generate_integer_argument,
             'drop': generate_null_argument,
             'end': generate_null_argument,
             'eq': generate_null_argument_from(2),
+            'get': generate_null_argument_from(2),
             'gt': generate_null_argument_from(2),
             'gte': generate_null_argument_from(2),
             'idiv': generate_null_argument_from(2),
             'jump': generate_label_argument,
             'jump_if_false': generate_label_argument,
+            'list': generate_integer_argument,
             'lt': generate_null_argument_from(2),
             'lte': generate_null_argument_from(2),
             'mod': generate_null_argument_from(2),
@@ -71,7 +74,9 @@ def generate_argument(instruction):
             'push': generate_symbol_argument,
             'push_integer': generate_integer_argument,
             'push_string': generate_string_argument,
+            'push_symbol': generate_symbol_argument,
             'return': generate_null_argument,
+            'structure': generate_integer_argument,
             'sub': generate_null_argument_from(2),
         }[instruction.instruction](instruction.argument)
 
index 49e7408..f9c7fa9 100644 (file)
@@ -39,6 +39,10 @@ def generate_symbol_literal(symbol):
 def generate_instruction_name_from_builtin(builtin):
     try:
         return {
+            # Environment operations
+            '__get__': 'get',
+
+            # Integer operations
             '__add__': 'add',
             '__integer_divide__': 'idiv',
             '__modular_divide__': 'mod',
@@ -46,12 +50,16 @@ def generate_instruction_name_from_builtin(builtin):
             '__negate__': 'neg',
             '__subtract__': 'sub',
 
+            # Boolean operations
             '__eq__': 'eq',
             '__neq__': 'neq',
             '__lt__': 'lt',
             '__lte__': 'lte',
             '__gt__': 'gt',
             '__gte__': 'gte',
+
+            # String operations
+            '__concat__': 'concat',
         }[builtin]
 
     except KeyError:
diff --git a/templates/frame.c b/templates/frame.c
new file mode 100644 (file)
index 0000000..3afd157
--- /dev/null
@@ -0,0 +1,17 @@
+struct Frame;
+typedef struct Frame Frame;
+struct Frame {
+
+  Environment* environment;
+  Frame* returnFrame;
+  size_t programCounter;
+};
+
+void Frame_initialize(Frame* self, Environment* environment, Frame* returnFrame, size_t programCounter) {
+  self->environment = environment;
+  self->returnFrame = returnFrame;
+  self->programCounter = programCounter;
+}
+
+void Frame_deinitialize(Frame* self) {
+}
index 5ca9f61..f51cdbf 100644 (file)
@@ -12,7 +12,9 @@ enum Type {
   BUILTIN,
   CLOSURE,
   INTEGER,
-  STRING
+  LIST,
+  STRING,
+  SYMBOL
 };
 
 enum Builtin;
@@ -37,14 +39,19 @@ 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 {
@@ -52,6 +59,11 @@ struct Object {
   Value value;
 };
 
+struct List {
+  Object head;
+  List* tail;
+};
+
 #define BUILTIN_NIL (Object) { BUILTIN, (Value)(Builtin)NIL }
 
 void Object_deinitialize(Object* self) {
@@ -99,6 +111,7 @@ union Argument {
   void* pointer;
   char* string;
   int32_t integer;
+  char* symbol;
 };
 
 void callBuiltinPow(Thread* thread, size_t argumentCount) {
@@ -206,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 %}
@@ -232,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 %}
@@ -258,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 %}
@@ -350,6 +426,14 @@ 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 %}
@@ -369,6 +453,10 @@ void inst_return(Thread* thread, Argument argument) {
   free(returnFrame);
 }
 
+void inst_structure(Thread* thread, Argument argument) {
+  assert(false);
+}
+
 struct Instruction;
 typedef const struct Instruction Instruction;
 struct Instruction {