BUILTIN,
CLOSURE,
INTEGER,
- STRING
+ LIST,
+ STRING,
+ STRUCTURE,
+ SYMBOL
};
enum Builtin;
typedef enum Builtin Builtin;
enum Builtin {
+ __FIELD__,
NIL,
POW,
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;
size_t entry;
};
+struct List;
+typedef struct List List;
+
+struct Structure;
+typedef struct Structure Structure;
+
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;
+ Structure* structure;
+ char* symbol;
};
-struct Object;
-typedef struct Object Object;
struct Object {
Type type;
Value value;
};
+struct List {
+ Object head;
+ List* tail;
+};
+
+struct Structure {
+ char* key;
+ Object value;
+ Structure* next;
+};
+
#define BUILTIN_NIL (Object) { BUILTIN, (Value)(Builtin)NIL }
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;
void* pointer;
char* string;
int32_t integer;
+ char* symbol;
};
+void callBuiltinField(Thread* thread, size_t argumentCount) {
+ assert(argumentCount == 2);
+
+ assert(!Stack_isEmpty(&(thread->stack)));
+ Object key = Stack_pop(&(thread->stack));
+ assert(key.type == STRING); // TODO Make this a symbol
+
+ assert(!Stack_isEmpty(&(thread->stack)));
+ Object structure = Stack_pop(&(thread->stack));
+ assert(structure.type == STRUCTURE);
+
+ while(structure.value.structure != NULL) {
+ if(strcmp(structure.value.structure->key, key.value.string) == 0) {
+ Stack_push(&(thread->stack), structure.value.structure->value);
+ return;
+ }
+ structure.value.structure = structure.value.structure->next;
+ }
+
+ assert(false); // Symbol wasn't found in structure
+}
+
void callBuiltinPow(Thread* thread, size_t argumentCount) {
assert(argumentCount == 2);
assert(!Stack_isEmpty(&(thread->stack)));
void callBuiltin(Thread* thread, Builtin b, size_t argumentCount) {
switch(b) {
+ case __FIELD__:
+ callBuiltinField(thread, argumentCount);
+ break;
+
case POW:
callBuiltinPow(thread, argumentCount);
break;
+
case PRINT:
callBuiltinPrint(thread, argumentCount);
break;
}
void callClosure(Thread* thread, Closure closure, size_t argumentCount) {
- assert(argumentCount == 0);
-
-
+ // TODO Find a way to assert the argument count
+
+ 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) {
}
}
+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 %}
{% include "comparison_instruction.c" %}
{% endwith %}
+void inst_get(Thread* thread, Argument argument) {
+ assert(!Stack_isEmpty(&(thread->stack)));
+ Object indexObject = Stack_pop(&(thread->stack));
+ assert(indexObject.type == INTEGER);
+ int32_t index = indexObject.value.integer;
+
+ assert(!Stack_isEmpty(&(thread->stack)));
+ Object listObject = Stack_pop(&(thread->stack));
+ assert(listObject.type == LIST);
+ List* list = listObject.value.list;
+
+ 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 %}
}
}
+void inst_list(Thread* thread, Argument argument) {
+ Object result;
+ result.type = LIST;
+ result.value.list = NULL;
+
+ int32_t count = argument.integer;
+
+ while(count > 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;
+ count--;
+ }
+
+ Stack_push(&(thread->stack), result);
+}
+
{% with name='lt', operation='<' %}
{% include "comparison_instruction.c" %}
{% endwith %}
void inst_push(Thread* thread, Argument argument) {
char* argumentString = argument.string;
- if(strcmp(argumentString, "false") == 0) {
+ if(strcmp(argumentString, "__field__") == 0) {
+ // TODO Make this an instruction
+ Object result;
+ result.type = BUILTIN;
+ result.value.builtin = __FIELD__;
+ Stack_push(&(thread->stack), result);
+ } else if(strcmp(argumentString, "false") == 0) {
Stack_push(&(thread->stack), (Object){ BOOLEAN, false });
- }else if(strcmp(argumentString, "pow") == 0) {
+ } else if(strcmp(argumentString, "pow") == 0) {
Object result;
result.type = BUILTIN;
result.value.builtin = POW;
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;
+
+ Stack_push(&(thread->stack), result);
+}
+
{% with name='sub', operation='-' %}
{% include "arithmetic_instruction.c" %}
{% endwith %}
void inst_return(Thread* thread, Argument argument) {
- assert(false);
+ 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) {
+ Object result;
+ result.type = STRUCTURE;
+ result.value.structure = NULL;
+
+ int32_t count = argument.integer;
+
+ while(count > 0) {
+ assert(!Stack_isEmpty(&(thread->stack)));
+ Object key = Stack_pop(&(thread->stack));
+ assert(key.type == SYMBOL);
+
+ assert(!Stack_isEmpty(&(thread->stack)));
+ Object value = Stack_pop(&(thread->stack));
+
+ Structure* node = malloc(sizeof(Structure));
+ node->key = key.value.string;
+ node->value = value;
+ node->next = result.value.structure;
+
+ result.value.structure = node;
+ count--;
+ }
+
+ Stack_push(&(thread->stack), result);
}
struct Instruction;