assert argument is None
return 'NULL'
+def generate_null_argument_from(argument_count):
+ def generator(argument):
+ assert isinstance(argument, int)
+ assert argument == argument_count
+ return 'NULL'
+ return generator
+
def generate_size_t_argument(argument):
assert isinstance(argument, int)
return '(size_t){}'.format(argument)
def generate_argument(instruction):
try:
return {
- 'add': generate_size_t_argument,
+ 'add': generate_null_argument_from(2),
+ 'call': generate_size_t_argument,
'drop': generate_null_argument,
'end': generate_null_argument,
- 'call': generate_size_t_argument,
- 'idiv': generate_size_t_argument,
- 'mod': generate_size_t_argument,
- 'mul': generate_size_t_argument,
- 'neg': generate_size_t_argument,
+ 'eq': generate_null_argument_from(2),
+ 'gt': generate_null_argument_from(2),
+ 'gte': generate_null_argument_from(2),
+ 'idiv': generate_null_argument_from(2),
+ 'lt': generate_null_argument_from(2),
+ 'lte': generate_null_argument_from(2),
+ 'mod': generate_null_argument_from(2),
+ 'mul': generate_null_argument_from(2),
+ 'neg': generate_null_argument_from(1),
+ 'neq': generate_null_argument_from(2),
'pop': generate_symbol_argument,
'push': generate_symbol_argument,
'push_integer': generate_integer_argument,
'push_string': generate_string_argument,
- 'sub': generate_size_t_argument,
+ 'sub': generate_null_argument_from(2),
}[instruction.instruction](instruction.argument)
except KeyError:
'__multiply__': 'mul',
'__negate__': 'neg',
'__subtract__': 'sub',
+
+ '__eq__': 'eq',
+ '__neq__': 'neq',
+ '__lt__': 'lt',
+ '__lte__': 'lte',
+ '__gt__': 'gt',
+ '__gte__': 'gte',
}[builtin]
except KeyError:
void {{ name }}(struct Thread* thread, const union Argument argument) {
- // We're going to reuse result as both the addend and the sum
+ // We're going to reuse result as both the first input and the result
assert(!Stack_isEmpty(&(thread->stack)));
Object result = Stack_pop(&(thread->stack));
assert(result.type == INTEGER);
assert(!Stack_isEmpty(&(thread->stack)));
Object other = Stack_pop(&(thread->stack));
- assert(result.type == INTEGER);
+ assert(other.type == INTEGER);
result.value.integer = other.value.integer {{ operation }} result.value.integer;
--- /dev/null
+void {{ name }}(struct Thread* thread, const union Argument argument) {
+ // We're going to reuse result as both the first input and the result
+ assert(!Stack_isEmpty(&(thread->stack)));
+ Object result = Stack_pop(&(thread->stack));
+ assert(result.type == INTEGER);
+
+ assert(!Stack_isEmpty(&(thread->stack)));
+ Object other = Stack_pop(&(thread->stack));
+ assert(other.type == INTEGER);
+
+ result.type = BOOLEAN;
+ result.value.boolean = other.value.integer {{ operation }} result.value.integer;
+
+ Stack_push(&(thread->stack), result);
+}
if(arg.value.boolean) printf("true");
else printf("false");
break;
+
case INTEGER:
printf("%i", arg.value.integer);
break;
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 %}
+{% 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 %}
+{% with name='neq', operation='!=' %}
+ {% include "comparison_instruction.c" %}
+{% endwith %}
+
void neg(struct Thread* thread, Argument argument) {
assert(!Stack_isEmpty(&(thread->stack)));
Object result = Stack_pop(&(thread->stack));