enum Type;
typedef enum Type Type;
enum Type {
+ BOOLEAN,
BUILTIN,
INTEGER,
STRING
typedef enum Builtin Builtin;
enum Builtin {
NIL,
+ POW,
PRINT
};
typedef union Value Value;
union Value {
Builtin builtin;
+ bool boolean;
char* string;
int32_t integer;
};
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
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;
{% 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 %}
{% 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)));
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) {
}
}
-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;
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;
struct Instruction;
typedef const struct Instruction Instruction;
struct Instruction {
- void (*instruction)(struct Thread*,const union Argument);
+ void (*instruction)(struct Thread*,Argument);
Argument argument;
};
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(