<commit_before>#include <stdio.h>
#include <stdlib.h>

#include "defs.h"
#include "error.h"
#include "spc.h"
#include "spvm_opcodes.h"

#define LBLLEN	32

static void gendecls(Node *node);
static void gendecl(Node *node);
static void genarray(Node *node);
static void genstatements(Node *node);
static void genstatement(Node *node);
static void genindex(Node *node);
static void genexp(Node *node);
static void genexp2(Node *node);
static void genop_exp(Node *node);
static void genop(Node *node);

static
char *
newlabel()
{
	static uvlong c;
	char *l;

	l = calloc(LBLLEN, sizeof(char));
	snprintf(l, LBLLEN, "l%llu", c++);
	return l;
}

void
genprog(Node *node)
{
	gendecls(node->left);
	genstatements(node->right);
	bprintf(out, "%s\n", spvm_op[STP]);
}

static
void
gendecls(Node *node)
{
	if (node == NULL)
		return;

	if (node->type != NODE_DECLS)
		die(EXIT_FAILURE, "Unexpected nodetype in gendecls().");

	gendecl(node->left);
	gendecls(node->right);		
}

static
void
gendecl(Node *node)
{
	if (node == NULL)
		panic("Unexpected nullpointer in gendecl().");
	bprintf(out, "%s $%s ", spvm_op[DS], node->data.sym->lexem);
	genarray(node->left);
}

static
void
genarray(Node *node)
{
	if (node == NULL)
		bprintf(out, "1\n");
	else
		bprintf(out, "%lu\n", node->data.val);
}

static
void
genstatements(Node *node)
{
	if (node == NULL)
		return;
	genstatement(node->left);
	genstatements(node->right);
	/* Fuck the specs, who needs NOPs? */
}

static
void
genstatement(Node *node)
{
	char *lbl1, *lbl2;

	if (node == NULL)
		panic("Unexpected nullpointer in genstatement().");
	switch(node->left->type) {
	case NODE_IDENT:
		genexp(node->right->right);
		bprintf(out, "%s $%s ", spvm_op[LA], node->left->data.sym->lexem);
		genindex(node->right->left);
		bprintf(out, "%s\n", spvm_op[STR]);
		break;
	case NODE_PRINT:
		genexp(node->left);
		bprintf(out, "%s\n", spvm_op[PRI]);
		break;
	case NODE_READ:
		bprintf(out, "%s\n%s $%S ", spvm_op[REA], spvm_op[LA],
		        node->left->left->data.sym->lexem);
		genindex(node->left->right);
		bprintf(out, "%s\n", spvm_op[STR]);
		break;
	case NODE_STATEMENTS: 
		genstatements(node->left);
		break;
	case NODE_IF:
		lbl1 = newlabel();
		lbl2 = newlabel();
		genexp(node->right);
		bprintf(out, "%s #%s\n", spvm_op[JIN], lbl1);
		genstatement(node->left->left);
		bprintf(out, "%s #%s\n#%s %s\n", spvm_op[JMP], lbl2, lbl1,
		        spvm_op[NOP]);
		genstatement(node->left->right);
		bprintf(out, "#%s %s\n", lbl2, spvm_op[NOP]);
		free(lbl2);
		free(lbl1);
		break;
	case NODE_WHILE:
		lbl1 = newlabel();
		lbl2 = newlabel();
		bprintf(out, "#%s %s\n", lbl1, spvm_op[NOP]);
		genexp(node->right);
		bprintf(out, "%s #%s\n", spvm_op[JIN], lbl2);
		genstatement(node->left->left);
		bprintf(out, "%s #%s\n#%s %s", spvm_op[JMP], lbl1, lbl2,
		        spvm_op[NOP]);
		free(lbl2);
		free(lbl1);
		break;
	default:
		warn("Unexpected node type %s in genstatement().", nodenames[node->left->type]);
	}
}

static
void
genexp(Node *node)
{
	if (node == NULL)
		panic("Unexpected nullpointer in genexp().");
	if (node->right == NULL)
		genexp2(node->left);
	else if (node->right->left->data.op == OP_GRTR) { /* fugly spec */
		genop_exp(node->right);
		genexp2(node->left);
		bprintf(out, "%s\n", spvm_op[LES]);
	} else {
		genexp2(node->left);
		genop_exp(node->right);
		if (node->right->left->data.op == OP_UNEQ)
			bprintf(out, "%s\n", spvm_op[NOT]);
	}
}

static
void
genindex(Node *node)
{<commit_msg>Fix codegen PRINT<commit_after>#include <stdio.h>
#include <stdlib.h>

#include "defs.h"
#include "error.h"
#include "spc.h"
#include "spvm_opcodes.h"

#define LBLLEN	32

static void gendecls(Node *node);
static void gendecl(Node *node);
static void genarray(Node *node);
static void genstatements(Node *node);
static void genstatement(Node *node);
static void genindex(Node *node);
static void genexp(Node *node);
static void genexp2(Node *node);
static void genop_exp(Node *node);
static void genop(Node *node);

static
char *
newlabel()
{
	static uvlong c;
	char *l;

	l = calloc(LBLLEN, sizeof(char));
	snprintf(l, LBLLEN, "l%llu", c++);
	return l;
}

void
genprog(Node *node)
{
	gendecls(node->left);
	genstatements(node->right);
	bprintf(out, "%s\n", spvm_op[STP]);
}

static
void
gendecls(Node *node)
{
	if (node == NULL)
		return;

	if (node->type != NODE_DECLS)
		die(EXIT_FAILURE, "Unexpected nodetype in gendecls().");

	gendecl(node->left);
	gendecls(node->right);		
}

static
void
gendecl(Node *node)
{
	if (node == NULL)
		panic("Unexpected nullpointer in gendecl().");
	bprintf(out, "%s $%s ", spvm_op[DS], node->data.sym->lexem);
	genarray(node->left);
}

static
void
genarray(Node *node)
{
	if (node == NULL)
		bprintf(out, "1\n");
	else
		bprintf(out, "%lu\n", node->data.val);
}

static
void
genstatements(Node *node)
{
	if ((node == NULL) || (node->left == NULL))
		return;
	genstatement(node->left);
	genstatements(node->right);
	/* Fuck the specs, who needs NOPs? */
}

static
void
genstatement(Node *node)
{
	char *lbl1, *lbl2;

	if (node == NULL)
		panic("Unexpected nullpointer in genstatement().");
	switch(node->left->type) {
	case NODE_IDENT:
		genexp(node->right->right);
		bprintf(out, "%s $%s ", spvm_op[LA], node->left->data.sym->lexem);
		genindex(node->right->left);
		bprintf(out, "%s\n", spvm_op[STR]);
		break;
	case NODE_PRINT:
		genexp(node->left->left);
		bprintf(out, "%s\n", spvm_op[PRI]);
		break;
	case NODE_READ:
		bprintf(out, "%s\n%s $%S ", spvm_op[REA], spvm_op[LA],
		        node->left->left->data.sym->lexem);
		genindex(node->left->right);
		bprintf(out, "%s\n", spvm_op[STR]);
		break;
	case NODE_STATEMENTS: 
		genstatements(node->left);
		break;
	case NODE_IF:
		lbl1 = newlabel();
		lbl2 = newlabel();
		genexp(node->right);
		bprintf(out, "%s #%s\n", spvm_op[JIN], lbl1);
		genstatement(node->left->left);
		bprintf(out, "%s #%s\n#%s %s\n", spvm_op[JMP], lbl2, lbl1,
		        spvm_op[NOP]);
		genstatement(node->left->right);
		bprintf(out, "#%s %s\n", lbl2, spvm_op[NOP]);
		free(lbl2);
		free(lbl1);
		break;
	case NODE_WHILE:
		lbl1 = newlabel();
		lbl2 = newlabel();
		bprintf(out, "#%s %s\n", lbl1, spvm_op[NOP]);
		genexp(node->right);
		bprintf(out, "%s #%s\n", spvm_op[JIN], lbl2);
		genstatement(node->left->left);
		bprintf(out, "%s #%s\n#%s %s", spvm_op[JMP], lbl1, lbl2,
		        spvm_op[NOP]);
		free(lbl2);
		free(lbl1);
		break;
	default:
		warn("Unexpected node type %s in genstatement().", nodenames[node->left->type]);
	}
}

static
void
genexp(Node *node)
{
	if (node == NULL)
		panic("Unexpected nullpointer in genexp().");
	if (node->right == NULL) {
		genexp2(node->left);
	} else if (node->right->left->data.op == OP_GRTR) { /* fugly spec */
		genop_exp(node->right);
		genexp2(node->left);
		bprintf(out, "%s\n", spvm_op[LES]);
	} else {
		genexp2(node->left);
		genop_exp(node->right);
		if (node->right->left->data.op == OP_UNEQ)
			bprintf(out, "%s\n", spvm_op[NOT]);
	}
	
}

static
void
genindex(Node *node)
{
{'fraction_non_alphanumeric': 0.1980426021876799, 'fraction_numerical': 0.007196315486470927, 'mean_word_length': 4.501979414093428, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 109, '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': '4785061', 'n_tokens_mistral': 3065, 'n_tokens_neox': 2929, 'n_words': 608}