--- /dev/null
+import os
+
+import jinja2
+
+import crossplatform_ir_generation
+
+TEMPLATE_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')
+
+def separate_labels_and_instructions(entry_list):
+ labels_to_instruction_indices = {}
+ instruction_list = []
+
+ for entry in entry_list:
+ if isinstance(entry, crossplatform_ir_generation.CIRInstruction):
+ instruction_list.append(entry)
+ elif isinstance(entry, crossplatform_ir_generation.CIRLabel):
+ labels_to_instruction_indices[entry.label] = len(instruction_list)
+
+ return labels_to_instruction_indices, tuple(instruction_list)
+
+def generate_integer_argument(argument):
+ assert isinstance(argument, int)
+ return '(int32_t){}'.format(argument)
+
+def generate_null_argument(argument):
+ assert argument is None
+ return 'NULL'
+
+def generate_size_t_argument(argument):
+ assert isinstance(argument, int)
+ return '(size_t){}'.format(argument)
+
+def generate_string_argument(argument):
+ return argument
+
+def generate_symbol_argument(argument):
+ assert argument.startswith('sym(') and argument.endswith(')')
+ return '"{}"'.format(argument[4:-1])
+
+def generate_argument(instruction):
+ try:
+ return {
+ 'drop': generate_null_argument,
+ 'end': generate_null_argument,
+ 'call': generate_size_t_argument,
+ 'push': generate_symbol_argument,
+ 'push_integer': generate_integer_argument,
+ 'push_string': generate_string_argument,
+ }[instruction.instruction](instruction.argument)
+
+ except KeyError:
+ import ipdb; ipdb.set_trace()
+
+def generate(ir):
+ environment = jinja2.Environment(loader=jinja2.FileSystemLoader(TEMPLATE_PATH))
+ template = environment.get_template('program2.c')
+
+ labels_to_instruction_indices, instruction_list = separate_labels_and_instructions(
+ ir.entry_list,
+ )
+
+ return template.render(
+ labels_to_instruction_indices=labels_to_instruction_indices,
+ instruction_list=instruction_list,
+ generate_argument=generate_argument,
+ )
),
)
-CPSListAppendStatement = collections.namedtuple(
- 'CPSListAppendStatement',
- (
- 'list_expression',
- 'item_expression',
- ),
-)
-
CPSPushStatement = collections.namedtuple(
'CPSPushStatement',
(
else_statement_list=else_statement_list,
)
-def convert_list_append_statement(statement):
- return CPSListAppendStatement(
- list_expression=convert_expression(statement.list_expression),
- item_expression=convert_expression(statement.item_expression),
- )
-
-
def convert_push_statement(statement):
return CPSPushStatement(
expression=convert_expression(statement.expression),
return {
normalization.NormalAssignmentStatement: convert_assignment_statement,
normalization.NormalExpressionStatement: convert_expression_statement,
- normalization.NormalListAppendStatement: convert_list_append_statement,
normalization.NormalPushStatement: convert_push_statement,
normalization.NormalVariableInitializationStatement: convert_variable_initialization_statement,
}[type(statement)](statement)
def generate_integer_literal_expression(counters, expression):
referenced_entry_list = ()
instruction_list = (CIRInstruction(
- instruction='push_value',
+ instruction='push_integer',
argument=generate_integer_literal(expression.integer),
),)
def generate_string_literal_expression(counters, expression):
referenced_entry_list = ()
instruction_list = (CIRInstruction(
- instruction='push_value',
+ instruction='push_string',
argument=generate_string_literal(expression.string),
),)
def generate_symbol_literal_expression(counters, expression):
referenced_entry_list = ()
instruction_list = (CIRInstruction(
- instruction='push_value',
+ instruction='push_symbol',
argument=generate_symbol_literal(expression.symbol),
),)
return CIRProgram(
entry_list=flatten(referenced_entry_list_list) + (
CIRLabel(label='__main__'),
- ) + flatten(instruction_list_list),
+ ) + flatten(instruction_list_list) + (
+ CIRInstruction(instruction='end', argument=None),
+ )
)
NO_ARGUMENT_INSTRUCTIONS = set([
import conversion
import crossplatform_ir_generation
import desugaring
+import c_generation
import normalization
import optimization
import parsing
normalized = normalization.normalize(desugared)
converted = conversion.convert(normalized)
-assert source_path.endswith('.fur')
-destination_path = source_path + '.c'
-
-with open(destination_path, 'w') as f:
- pass
- #f.write(generated)
-
-# This is the crossplatform IR generation path
crossplatform_ir = crossplatform_ir_generation.generate(converted)
optimized = optimization.optimize(crossplatform_ir)
outputted = crossplatform_ir_generation.output(optimized)
print(outputted)
+
+generated = c_generation.generate(optimized)
+
+assert source_path.endswith('.fur')
+destination_path = source_path + '.c'
+
+with open(destination_path, 'w') as f:
+ f.write(generated)
--- /dev/null
+#include<assert.h>
+#include<stdbool.h>
+#include<stdint.h>
+#include<stdio.h>
+#include<stdlib.h>
+#include<string.h>
+
+enum Type;
+typedef enum Type Type;
+enum Type {
+ BUILTIN,
+ INTEGER,
+ STRING
+};
+
+enum Builtin;
+typedef enum Builtin Builtin;
+enum Builtin {
+ NIL,
+ PRINT
+};
+
+union Value;
+typedef union Value Value;
+union Value {
+ Builtin builtin;
+ char* string;
+ int32_t integer;
+};
+
+struct Object;
+typedef struct Object Object;
+struct Object {
+ Type type;
+ Value value;
+};
+
+#define BUILTIN_NIL (Object) { BUILTIN, (Value)(Builtin)NIL }
+
+void Object_deinitialize(Object* self) {
+}
+
+{% include "stack.c" %}
+
+struct Thread;
+typedef struct Thread Thread;
+struct Thread {
+ Stack stack;
+ size_t program_counter;
+};
+
+void Thread_initialize(Thread* self, size_t program_counter) {
+ Stack_initialize(&(self->stack));
+ self->program_counter = program_counter;
+}
+
+void Thread_deinitialize(Thread* self) {
+ Stack_deinitialize(&(self->stack));
+}
+
+union Argument;
+typedef const union Argument Argument;
+union Argument {
+ size_t label;
+ void* pointer;
+ char* string;
+ int32_t integer;
+};
+
+void call(struct Thread* thread, const union Argument argument) {
+ assert(!Stack_isEmpty(&(thread->stack)));
+ Object f = Stack_pop(&(thread->stack));
+
+ switch(f.type) {
+ case BUILTIN:
+ switch(f.value.builtin) {
+ case PRINT:
+ {
+ // TODO Handle multiple arguments
+ assert(!Stack_isEmpty(&(thread->stack)));
+ Object arg = Stack_pop(&(thread->stack));
+
+ switch(arg.type) {
+ case INTEGER:
+ printf("%i", arg.value.integer);
+ break;
+
+ case STRING:
+ printf("%s", arg.value.string);
+ break;
+
+ default:
+ assert(0);
+ }
+
+ Stack_push(&(thread->stack), BUILTIN_NIL);
+ }
+ break;
+
+ default:
+ assert(false);
+ }
+ break;
+
+ default:
+ assert(false);
+ }
+}
+
+void drop(struct Thread* thread, const union 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 push(struct Thread* thread, const union Argument argument) {
+ char* argumentString = argument.string;
+
+ Object result;
+
+ if(strcmp(argumentString, "print") == 0) {
+ result.type = BUILTIN;
+ result.value.builtin = PRINT;
+ } else {
+ assert(false);
+ }
+
+ Stack_push(&(thread->stack), result);
+}
+
+void push_integer(struct Thread* thread, const union 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) {
+ Object result;
+ result.type = STRING;
+ result.value.string = argument.string;
+
+ Stack_push(&(thread->stack), result);
+}
+
+struct Instruction;
+typedef const struct Instruction Instruction;
+struct Instruction {
+ void (*instruction)(struct Thread*,const union Argument);
+ Argument argument;
+};
+
+{% for label in labels_to_instruction_indices.keys() %}
+#define LABEL_{{ label }} {{ labels_to_instruction_indices[label] }}
+{% endfor %}
+
+const Instruction program[] = {
+{% for instruction in instruction_list %}
+ (Instruction){ {{ instruction.instruction }}, (Argument){{ generate_argument(instruction) }} },
+{% endfor %}
+};
+
+int main() {
+ Thread thread;
+ Thread_initialize(&thread, 0);
+
+ for(; program[thread.program_counter].instruction != end; thread.program_counter++) {
+ program[thread.program_counter].instruction(
+ &thread,
+ program[thread.program_counter].argument
+ );
+ }
+
+ Thread_deinitialize(&thread);
+
+ return 0;
+}
--- /dev/null
+struct StackNode;
+typedef struct StackNode StackNode;
+struct StackNode {
+ Object value;
+ StackNode* next;
+};
+
+struct Stack;
+typedef struct Stack Stack;
+struct Stack {
+ StackNode* top;
+};
+
+void Stack_initialize(Stack* self) {
+ self->top = NULL;
+}
+
+bool Stack_isEmpty(Stack* self) {
+ return self->top == NULL;
+}
+
+Object Stack_pop(Stack*);
+
+void Stack_deinitialize(Stack* self) {
+ while(self->top != NULL) {
+ Object o = Stack_pop(self);
+ Object_deinitialize(&o);
+ }
+}
+
+void Stack_push(Stack* self, Object value) {
+ StackNode* node = malloc(sizeof(StackNode));
+ node->value = value;
+ node->next = self->top;
+ self->top = node;
+}
+
+Object Stack_pop(Stack* self) {
+ assert(self->top != NULL);
+
+ StackNode* node = self->top;
+ self->top = node->next;
+
+ Object result = node->value;
+ free(node);
+ return result;
+}