<commit_before>#include "codegen.h"

/**
 * A boilerplate for our generated C files. Eventually
 * we should only write this into one file included into
 * all the headers instead of generate on top of all the header
 * files?
 *
 * It includes a few vital header files that will eventually
 * be written in Alloy itself. Also a few aliases for certain
 * types.
 */
const char *BOILERPLATE =
"#include <stdbool.h>\n"
"#include <stddef.h>\n"
"#include <stdarg.h>\n"
"\n"
"typedef char *str;" CC_NEWLINE
"typedef size_t usize;" CC_NEWLINE
"typedef unsigned char u8;" CC_NEWLINE
"typedef unsigned short u16;" CC_NEWLINE
"typedef unsigned int u32;" CC_NEWLINE
"typedef unsigned long long u64;" CC_NEWLINE
"typedef char i8;" CC_NEWLINE
"typedef short i16;" CC_NEWLINE
"typedef int i32;" CC_NEWLINE
"typedef long long i64;" CC_NEWLINE
"typedef float f32;" CC_NEWLINE
"typedef double f64;" CC_NEWLINE
;

/**
 * Node names corresponding to their enumerated counterpart
 */
const char *NODE_NAME[] = {
	"IDENTIFIER_LIST_NODE", "IDENTIFIER_NODE", "LITERAL_NODE", "BINARY_EXPR_NODE",
	"PRIMARY_EXPR_NODE", "EXPR_NODE", "TYPE_NAME_NODE", "TYPE_LIT_NODE", "PAREN_EXPR_NODE",
	"ARRAY_TYPE_NODE", "POINTER_TYPE_NODE", "FIELD_DECL_NODE", "UNARY_EXPR_NODE",
	"FIELD_DECL_LIST_NODE", "STRUCT_DECL_NODE", "STATEMENT_LIST_NODE",
	"BLOCK_NODE", "PARAMETER_SECTION_NODE", "PARAMETERS_NODE", "IMPL_NODE", "ENUM_DECL_NODE",
	"FUNCTION_SIGNATURE_NODE", "FUNCTION_DECL_NODE", "VARIABLE_DECL_NODE", "FUNCTION_CALL_NODE",
	"DECLARATION_NODE", "INC_DEC_STAT_NODE", "RETURN_STAT_NODE", "BREAK_STAT_NODE",
	"CONTINUE_STAT_NODE", "LEAVE_STAT_NODE", "ASSIGNMENT_NODE", "UNSTRUCTURED_STATEMENT_NODE",
	"ELSE_STAT_NODE", "IF_STAT_NODE", "MATCH_CLAUSE_STAT", "MATCH_STAT_NODE", "FOR_STAT_NODE",
	"STRUCTURED_STATEMENT_NODE", "STATEMENT_NODE", "TYPE_NODE", "POINTER_FREE_NODE", "TUPLE_TYPE_NODE",
	"TUPLE_EXPR_NODE", "OPTION_TYPE_NODE", 
	"MACRO_NODE", "USE_MACRO_NODE", "LINKER_FLAG_MACRO_NODE", "EXPR_STAT_NODE", "ARRAY_INITIALIZER_NODE"
};

CodeGenerator *createCodeGenerator(Vector *sourceFiles) {
	CodeGenerator *self = safeMalloc(sizeof(*self));
	self->abstractSyntaxTree = NULL;
	self->currentNode = 0;
	self->sourceFiles = sourceFiles;
	self->LINKER_FLAGS = sdsempty();
	return self;
}

void emitCode(CodeGenerator *self, const char *fmt, ...) {
	va_list args;
	va_start(args, fmt);

	switch (self->writeState) {
		case WRITE_SOURCE_STATE:
			vfprintf(self->currentSourceFile->outputFile, fmt, args);
			break;
		case WRITE_HEADER_STATE:
			vfprintf(self->currentSourceFile->headerFile->outputFile, fmt, args);
			break;
	}

	va_end(args);
}

void consumeAstNode(CodeGenerator *self) {
	self->currentNode += 1;
}

void consumeAstNodeBy(CodeGenerator *self, int amount) {
	self->currentNode += amount;
}

void emitLiteral(CodeGenerator *self, Literal *lit) {
	emitCode(self, "%s", lit->value);
}

void emitBinaryExpr(CodeGenerator *self, BinaryExpr *expr) {
	emitExpression(self, expr->lhand);
	emitCode(self, "%s", expr->binaryOp);
	emitExpression(self, expr->rhand);
}

void emitUnaryExpr(CodeGenerator *self, UnaryExpr *expr) {
	if (!strcmp(expr->unaryOp, "^")) {
		// change it to a dereference
		// im pretty sure this shouldn't conflict with
		// XOR?
		emitCode(self, "*");
	}
	else {
		emitCode(self, "%s", expr->unaryOp);
	}
	emitExpression(self, expr->lhand);
}

void emitArrayInitializer(CodeGenerator *self, ArrayInitializer *arr) {
	if (arr == NULL || arr->values) return;
	emitCode(self, "{");
	for (int i = 0; i < arr->values->size; i++) {
		emitExpression(self, getVectorItem(arr->values, i));
		if (arr->values->size > 1 && i != arr->values->size - 1) {
			emitCode(self, ", ");
		}
	}
	emitCode(self, "}");
}

void emitExpression(CodeGenerator *self, Expression *expr) {
	switch (expr->exprType) {<commit_msg>fixed array emit<commit_after>#include "codegen.h"

/**
 * A boilerplate for our generated C files. Eventually
 * we should only write this into one file included into
 * all the headers instead of generate on top of all the header
 * files?
 *
 * It includes a few vital header files that will eventually
 * be written in Alloy itself. Also a few aliases for certain
 * types.
 */
const char *BOILERPLATE =
"#include <stdbool.h>\n"
"#include <stddef.h>\n"
"#include <stdarg.h>\n"
"\n"
"typedef char *str;" CC_NEWLINE
"typedef size_t usize;" CC_NEWLINE
"typedef unsigned char u8;" CC_NEWLINE
"typedef unsigned short u16;" CC_NEWLINE
"typedef unsigned int u32;" CC_NEWLINE
"typedef unsigned long long u64;" CC_NEWLINE
"typedef char i8;" CC_NEWLINE
"typedef short i16;" CC_NEWLINE
"typedef int i32;" CC_NEWLINE
"typedef long long i64;" CC_NEWLINE
"typedef float f32;" CC_NEWLINE
"typedef double f64;" CC_NEWLINE
;

/**
 * Node names corresponding to their enumerated counterpart
 */
const char *NODE_NAME[] = {
	"IDENTIFIER_LIST_NODE", "IDENTIFIER_NODE", "LITERAL_NODE", "BINARY_EXPR_NODE",
	"PRIMARY_EXPR_NODE", "EXPR_NODE", "TYPE_NAME_NODE", "TYPE_LIT_NODE", "PAREN_EXPR_NODE",
	"ARRAY_TYPE_NODE", "POINTER_TYPE_NODE", "FIELD_DECL_NODE", "UNARY_EXPR_NODE",
	"FIELD_DECL_LIST_NODE", "STRUCT_DECL_NODE", "STATEMENT_LIST_NODE",
	"BLOCK_NODE", "PARAMETER_SECTION_NODE", "PARAMETERS_NODE", "IMPL_NODE", "ENUM_DECL_NODE",
	"FUNCTION_SIGNATURE_NODE", "FUNCTION_DECL_NODE", "VARIABLE_DECL_NODE", "FUNCTION_CALL_NODE",
	"DECLARATION_NODE", "INC_DEC_STAT_NODE", "RETURN_STAT_NODE", "BREAK_STAT_NODE",
	"CONTINUE_STAT_NODE", "LEAVE_STAT_NODE", "ASSIGNMENT_NODE", "UNSTRUCTURED_STATEMENT_NODE",
	"ELSE_STAT_NODE", "IF_STAT_NODE", "MATCH_CLAUSE_STAT", "MATCH_STAT_NODE", "FOR_STAT_NODE",
	"STRUCTURED_STATEMENT_NODE", "STATEMENT_NODE", "TYPE_NODE", "POINTER_FREE_NODE", "TUPLE_TYPE_NODE",
	"TUPLE_EXPR_NODE", "OPTION_TYPE_NODE", 
	"MACRO_NODE", "USE_MACRO_NODE", "LINKER_FLAG_MACRO_NODE", "EXPR_STAT_NODE", "ARRAY_INITIALIZER_NODE"
};

CodeGenerator *createCodeGenerator(Vector *sourceFiles) {
	CodeGenerator *self = safeMalloc(sizeof(*self));
	self->abstractSyntaxTree = NULL;
	self->currentNode = 0;
	self->sourceFiles = sourceFiles;
	self->LINKER_FLAGS = sdsempty();
	return self;
}

void emitCode(CodeGenerator *self, const char *fmt, ...) {
	va_list args;
	va_start(args, fmt);

	switch (self->writeState) {
		case WRITE_SOURCE_STATE:
			vfprintf(self->currentSourceFile->outputFile, fmt, args);
			break;
		case WRITE_HEADER_STATE:
			vfprintf(self->currentSourceFile->headerFile->outputFile, fmt, args);
			break;
	}

	va_end(args);
}

void consumeAstNode(CodeGenerator *self) {
	self->currentNode += 1;
}

void consumeAstNodeBy(CodeGenerator *self, int amount) {
	self->currentNode += amount;
}

void emitLiteral(CodeGenerator *self, Literal *lit) {
	emitCode(self, "%s", lit->value);
}

void emitBinaryExpr(CodeGenerator *self, BinaryExpr *expr) {
	emitExpression(self, expr->lhand);
	emitCode(self, "%s", expr->binaryOp);
	emitExpression(self, expr->rhand);
}

void emitUnaryExpr(CodeGenerator *self, UnaryExpr *expr) {
	if (!strcmp(expr->unaryOp, "^")) {
		// change it to a dereference
		// im pretty sure this shouldn't conflict with
		// XOR?
		emitCode(self, "*");
	}
	else {
		emitCode(self, "%s", expr->unaryOp);
	}
	emitExpression(self, expr->lhand);
}

void emitArrayInitializer(CodeGenerator *self, ArrayInitializer *arr) {
	if (arr == NULL || arr->values == NULL) {
		printf("something is null, we're leaving..\n");
		return;
	}
	emitCode(self, "{");
	for (int i = 0; i < arr->values->size; i++) {
		emitExpression(self, getVectorItem(arr->values, i));
		if (arr->values->size > 1 && i != arr->values->size - 1) {
			emitCode(self, ", ");
		}
	}
	emitCode(self, "}");
}

void emitExpression(CodeGenerator *self, Expression *expr) {
	switch (expr->exprType) {
{'fraction_non_alphanumeric': 0.1430062630480167, 'fraction_numerical': 0.0060020876826722335, 'mean_word_length': 5.993613138686132, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 67, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4401574', 'n_tokens_mistral': 2869, 'n_tokens_neox': 2734, 'n_words': 638}