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

#include "cc1.h"
#include "../util/util.h"
#include "tree.h"
#include "fold.h"
#include "../util/util.h"
#include "sym.h"
#include "../util/platform.h"
#include "const.h"
#include "asm.h"

#define DIE_UNDECL_SPEL(sp) \
		die_at(&e->where, "undeclared identifier \"%s\" (%s:%d)", sp, __FILE__, __LINE__)

#define DIE_UNDECL() DIE_UNDECL_SPEL(e->spel)

void fold_expr(expr *e, symtable *stab);
void fold_code(tree *t);

int fold_is_lvalue(expr *e)
{
	/*
	 * valid lvaluess:
	 *
	 *   x = 5;
	 *   *(expr) = 5;
	 *   (cast *)expr = 5;
	 *
	 * also can't be const
	 */
	if(e->tree_type->type->spec & spec_const)
		die_at(&e->where, "can't modify const expression");

	return
		 e->type == expr_identifier ||
		(e->type == expr_op && e->op == op_deref && fold_is_lvalue(e->lhs)) ||
		(e->type == expr_cast && e->lhs->tree_type->ptr_depth) /* assignment to pointer-deref */
		;
}

#define GET_TREE_TYPE(from) \
	do{ \
		/*if(e->tree_type) \
			decl_free(e->tree_type);*/ \
		e->tree_type = decl_copy(from); \
		e->tree_type->spel = NULL; \
	}while(0)

void fold_funcall(expr *e, symtable *stab)
{
	decl *df;

	if(e->funcargs){
		expr **iter;
		for(iter = e->funcargs; *iter; iter++)
			fold_expr(*iter, stab);
	}

	if(!e->sym){
		df = decl_new_where(&e->where);

		df->func = function_new();

		df->type->primitive = type_int;
		df->spel = e->spel;

		warn_at(&e->where, "implicit declaration of function \"%s\"", e->spel);

		e->sym = symtab_add(symtab_grandparent(stab), df, sym_func);

		df->sym = NULL;
		/*
		 * fold() sets df->sym below,
		 * and doesn't expect it to be set.
		 * -> df is now part of the global sym table,
		 * having just been added via grandparent()
		 */

		/* set up the function args to correspond with the arg types */
		if(e->funcargs){
			expr **iter;
			for(iter = e->funcargs; *iter; iter++)
				dynarray_add((void ***)&df->func->args, (*iter)->tree_type);
		}
	}else{
		df = e->sym->decl;
	}

	GET_TREE_TYPE(e->sym->decl); /* XXX: check */

	/* func count comparison, only if the func has arg-decls, or the func is f(void) */
	if(df->func->args || df->func->args_void){
		expr **iter_arg;
		decl **iter_decl;
		int count_decl, count_arg;
		int i;

		count_decl = count_arg = 0;

		for(iter_arg  = e->funcargs;    iter_arg  && *iter_arg;  iter_arg++,  count_arg++);
		for(iter_decl = df->func->args; iter_decl && *iter_decl; iter_decl++, count_decl++);

		if(count_decl != count_arg && (df->func->variadic ? count_arg < count_decl : 1)){
			die_at(&e->where, "too %s arguments to function %s",
					count_arg > count_decl ? "many" : "few",
					df->spel);
		}

		if(e->funcargs){
			for(i = 0, iter_decl = df->func->args, iter_arg = e->funcargs;
					iter_decl[i];
					i++){
				/* TODO: -fstrict-types - changes the below 0 to a 1 */
				if(!decl_equal(iter_arg[i]->tree_type, iter_decl[i], 0)){
					char buf[DECL_STATIC_BUFSIZ];
					strcpy(buf, decl_to_str(iter_arg[i]->tree_type));
					warn_at(&e->where, "mismatching arguments for arg %d to %s: got %s, expected %s",
							i + 1, df->spel, buf, decl_to_str(iter_decl[i]));
				}
			}
		}
	}
}

void fold_assignment(expr *e, symtable *stab)
{
	if(!fold_is_lvalue(e->lhs))
		die_at(&e->lhs->where, "not an lvalue");

	fold_expr(e->lhs, stab);
	fold_expr(e->rhs, stab);


	if(!e->sym){
		/* need this here, since the generic sym-assignment does it from ->spel and not with assigning_to either */
		e->sym = symtab_search(stab, e->lhs->spel);

		if(!e->sym)
			DIE_UNDECL_SPEL(e->lhs->spel);
	}


	/* read the tree_type from what we're assigning to, not the expr */
	GET_TREE_TYPE(e->sym->decl);

	/* type check */
	if(!decl_equal(e->lhs->tree_type, e->rhs->tree_type, 0)){
		char buf[DECL_STATIC_BUFSIZ];

		strcpy(buf, decl_to_str(e->lhs->tree_type));

		warn_at(&e->where, "assignment type mismatch: got %s, expected %s",
				decl_to_str(e->rhs->tree_type), buf);
	}
}<commit_msg>Added die() for void assignments<commit_after>#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

#include "cc1.h"
#include "../util/util.h"
#include "tree.h"
#include "fold.h"
#include "../util/util.h"
#include "sym.h"
#include "../util/platform.h"
#include "const.h"
#include "asm.h"

#define DIE_UNDECL_SPEL(sp) \
		die_at(&e->where, "undeclared identifier \"%s\" (%s:%d)", sp, __FILE__, __LINE__)

#define DIE_UNDECL() DIE_UNDECL_SPEL(e->spel)

void fold_expr(expr *e, symtable *stab);
void fold_code(tree *t);

int fold_is_lvalue(expr *e)
{
	/*
	 * valid lvaluess:
	 *
	 *   x = 5;
	 *   *(expr) = 5;
	 *   (cast *)expr = 5;
	 *
	 * also can't be const
	 */
	if(e->tree_type->type->spec & spec_const)
		die_at(&e->where, "can't modify const expression");

	return
		 e->type == expr_identifier ||
		(e->type == expr_op && e->op == op_deref && fold_is_lvalue(e->lhs)) ||
		(e->type == expr_cast && e->lhs->tree_type->ptr_depth) /* assignment to pointer-deref */
		;
}

#define GET_TREE_TYPE(from) \
	do{ \
		/*if(e->tree_type) \
			decl_free(e->tree_type);*/ \
		e->tree_type = decl_copy(from); \
		e->tree_type->spel = NULL; \
	}while(0)

void fold_funcall(expr *e, symtable *stab)
{
	decl *df;

	if(e->funcargs){
		expr **iter;
		for(iter = e->funcargs; *iter; iter++)
			fold_expr(*iter, stab);
	}

	if(!e->sym){
		df = decl_new_where(&e->where);

		df->func = function_new();

		df->type->primitive = type_int;
		df->spel = e->spel;

		warn_at(&e->where, "implicit declaration of function \"%s\"", e->spel);

		e->sym = symtab_add(symtab_grandparent(stab), df, sym_func);

		df->sym = NULL;
		/*
		 * fold() sets df->sym below,
		 * and doesn't expect it to be set.
		 * -> df is now part of the global sym table,
		 * having just been added via grandparent()
		 */

		/* set up the function args to correspond with the arg types */
		if(e->funcargs){
			expr **iter;
			for(iter = e->funcargs; *iter; iter++)
				dynarray_add((void ***)&df->func->args, (*iter)->tree_type);
		}
	}else{
		df = e->sym->decl;
	}

	GET_TREE_TYPE(e->sym->decl); /* XXX: check */

	/* func count comparison, only if the func has arg-decls, or the func is f(void) */
	if(df->func->args || df->func->args_void){
		expr **iter_arg;
		decl **iter_decl;
		int count_decl, count_arg;
		int i;

		count_decl = count_arg = 0;

		for(iter_arg  = e->funcargs;    iter_arg  && *iter_arg;  iter_arg++,  count_arg++);
		for(iter_decl = df->func->args; iter_decl && *iter_decl; iter_decl++, count_decl++);

		if(count_decl != count_arg && (df->func->variadic ? count_arg < count_decl : 1)){
			die_at(&e->where, "too %s arguments to function %s",
					count_arg > count_decl ? "many" : "few",
					df->spel);
		}

		if(e->funcargs){
			for(i = 0, iter_decl = df->func->args, iter_arg = e->funcargs;
					iter_decl[i];
					i++){
				/* TODO: -fstrict-types - changes the below 0 to a 1 */
				if(!decl_equal(iter_arg[i]->tree_type, iter_decl[i], 0)){
					char buf[DECL_STATIC_BUFSIZ];
					void (*fn)(where *, const char *, ...);

					fn = iter_arg[i]->tree_type->type->primitive == type_void ? die_at : warn_at;

					strcpy(buf, decl_to_str(iter_arg[i]->tree_type));
					fn(&e->where, "mismatching arguments for arg %d to %s: got %s, expected %s",
							i + 1, df->spel, buf, decl_to_str(iter_decl[i]));
				}
			}
		}
	}
}

void fold_assignment(expr *e, symtable *stab)
{
	if(!fold_is_lvalue(e->lhs))
		die_at(&e->lhs->where, "not an lvalue");

	fold_expr(e->lhs, stab);
	fold_expr(e->rhs, stab);


	if(!e->sym){
		/* need this here, since the generic sym-assignment does it from ->spel and not with assigning_to either */
		e->sym = symtab_search(stab, e->lhs->spel);

		if(!e->sym)
			DIE_UNDECL_SPEL(e->lhs->spel);
	}


	/* read the tree_type from what we're assigning to, not the expr */
	GET_TREE_TYPE(e->sym->decl);

	/* type check */
	if(!decl_equal(e->lhs->tree_type, e->rhs->tree_type, 0)){
		char buf[DECL_STATIC_BUFSIZ];
		void (*fn)(where *, const char *, ...);

		strcpy(buf, decl_to_str(e->lhs->tree_type));

		if(e->lhs->tree_type->type->primitive == type_void ||
		   e->rhs->tree_type->type->primitive == type_void)
			fn = die_at;
		else
			fn = warn_at;

		fn(&e->where, "assignment type mismatch: got %s, expected %s",
				decl_to_str(e->rhs->tree_type), buf);
	}
}
{'fraction_non_alphanumeric': 0.19263387448509814, 'fraction_numerical': 0.003149987884661982, 'mean_word_length': 3.4986376021798367, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 196, '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': '567837', 'n_tokens_mistral': 3647, 'n_tokens_neox': 3276, 'n_words': 730}