WONKY



LOG | FILES | OVERVIEW


#ifndef WONKY_PROGRAM_C
#define WONKY_PROGRAM_C WONKY_PROGRAM_C
#/*Don't mind me*/include/*When I grow up I want to be a new line*/ <program.h>


struct Program* get_program()
{
	struct Program *ret;
	ret=wonky_malloc(sizeof(struct Program));
	ret->translation_units=wonky_malloc(sizeof(struct Queue));
	ret->source_files=wonky_malloc(sizeof(struct Queue));
	ret->errors=wonky_malloc(sizeof(struct Queue));
	ret->types=wonky_malloc(sizeof(struct Map));
	ret->continue_to_parse=1;

	ret->preprocessing_translation_units=wonky_malloc(sizeof(struct Map));
	ret->preprocessing_translation_units_to_be_compiled=wonky_malloc(sizeof(struct Queue));

	ret->functions_without_a_definition=wonky_malloc(sizeof(struct Queue));
	ret->external_objects_without_an_initialiser=wonky_malloc(sizeof(struct Queue));




	ret->external_linkage=get_linkage();

	Queue_Init(ret->translation_units);
	Queue_Init(ret->source_files);
	Queue_Init(ret->errors);
	Queue_Init(ret->preprocessing_translation_units_to_be_compiled);
	Queue_Init(ret->functions_without_a_definition);
	Queue_Init(ret->external_objects_without_an_initialiser);



	Map_Init(ret->types);
	Map_Init(ret->preprocessing_translation_units);

	ret->current_translation_unit_number=1;

	return ret;
}

struct Translation_Data* get_translation_data(struct Preprocessing_Translation_Unit *start_unit,struct Linkage *internal_linkage,struct Program *program)
{
	struct Translation_Data *ret;
	ret=wonky_malloc(sizeof(struct Translation_Data));

	ret->token_pointer=get_token_ptr(start_unit,program);
	ret->internal_linkage=internal_linkage;
	ret->program=program;

	return ret;
}
struct Translation_Data* get_dummy_translation_data_for_parsing_const_expressions(struct Token_Pointer *ptr)
{
	struct Translation_Data *ret;
	ret=wonky_malloc(sizeof(struct Translation_Data));

	ret->token_pointer=ptr;
	ret->internal_linkage=get_linkage();
	ret->program=ptr->program;

	return ret;
}
struct Program* parse_program(char **base_source_names)
{
	struct Source_File *base_file;
	struct Program *program;
	struct Translation_Data *hold_translation_data;
	struct Queue_Node *hold_node;

	char *this_directory[]={"./","",NULL};

	wonky_assert(base_source_names!=NULL);

	if(*base_source_names==NULL)
		return NULL;

	program=get_program();

	do
	{
		base_file=get_source_file_from_string(*base_source_names,gstrnlen(*base_source_names,1000),program);
		if(base_file==NULL)
			break;
		Queue_Push(program->preprocessing_translation_units_to_be_compiled,lex(base_file,program));
	}while(*(++base_source_names) != NULL);

	if(program_has_errors(program))
		return program;	

	for(
		hold_node=program->preprocessing_translation_units_to_be_compiled->first;
		hold_node!=NULL;
		hold_node=hold_node->prev
	   )
	{
		hold_translation_data=get_translation_data(
					(struct Preprocessing_Translation_Unit*)hold_node->data,
					get_linkage(),
					program);

		Queue_Push(
				program->translation_units,
				parse_translation_unit(hold_translation_data)
			  );
		++program->current_translation_unit_number;
	}


	find_functions_without_definitions(program);
	find_external_objects_without_an_initialiser(program);
	
	return program;
}
struct Preprocessing_Translation_Unit* program_get_translation_unit(struct Program *program,char *filename,size_t filename_size)
{
	struct Preprocessing_Translation_Unit *ret;
	struct Source_File *hold_src;

	
	ret=Map_Check(program->preprocessing_translation_units,filename,filename_size);

	if(ret==NULL)
	{
		hold_src=get_source_file_from_string(filename,filename_size,program);
		if(hold_src==NULL)
			return NULL;
		ret=lex(hold_src,program);
		if(ret==NULL)
			return NULL;
		Map_Push(program->preprocessing_translation_units,filename,filename_size,ret);
	}

	return ret;
}
void program_stop_parsing(struct Program *program)
{
	program->continue_to_parse=0;
}

_Bool has_new_errors(struct Translation_Data *translation_data)
{
	return program_has_new_errors(translation_data->program);
}

_Bool program_has_new_errors(struct Program *program)
{
	if(program->errors->size != program->number_of_errors_when_last_checked)
	{
		program->number_of_errors_when_last_checked=program->errors->size;
		return 1;
	}else
	{
		return 0;
	}
}
_Bool program_has_errors(struct Program *program)
{
	if(program->errors->size != program->number_of_errors_when_last_checked)
	{
		return 1;
	}else
	{
		return 0;
	}
}
void delete_program(struct Program *program)
{
	while(program->translation_units->size>0)
		delete_ast(Queue_Pop(program->translation_units));
	wonky_free(program->translation_units);



	while(program->source_files->size>0)
		delete_source_file(Queue_Pop(program->source_files));
	wonky_free(program->source_files);


	while(program->errors->size>0)
		delete_error(program,Queue_Pop(program->errors));
	wonky_free(program->errors);


	delete_linkage(program->external_linkage);

	/*BEWARE*/
	Map_Map(program->types,delete_type);
	Map_Destroy(program->types);
	wonky_free(program->types);

	wonky_free(program);

}
void delete_translation_data(struct Translation_Data *translation_data)
{
	wonky_assert(translation_data->token_pointer!=NULL);
	delete_token_ptr(translation_data->token_pointer);
	wonky_free(translation_data);
	
}
_Bool has_no_tokens(struct Translation_Data *translation_data)
{
	return !token_ptr_has_remaining_tokens(translation_data->token_pointer);
}

/*TODO*/
void find_functions_without_definitions(struct Program *program)
{
	Map_Map_Extended(program->external_linkage->ids,(void (*)(void*,void*))push_if_tree_is_undefined_function,program->functions_without_a_definition);
}
/*TODO*/
void find_external_objects_without_an_initialiser(struct Program *program)
{
	Map_Map_Extended(program->external_linkage->ids,(void (*)(void*,void*))push_if_tree_is_uninitialised_object,program->external_objects_without_an_initialiser);
}
void push_if_tree_is_undefined_function(struct AST *tree,struct Queue *where_to_push)
{
	if(tree->type==ST_FUNCTION_DECLARATION)
		Queue_Push(where_to_push,tree);
}
void push_if_tree_is_uninitialised_object(struct AST *tree,struct Queue *where_to_push)
{
	if(tree->type==ST_OBJECT_DECLARATION)
	{
		struct AST_Object_Declaration *declaration;
		declaration=(struct AST_Object_Declaration*)tree;
		if(declaration->initializer==NULL)
			Queue_Push(where_to_push,tree);
	}
}
_Bool check(struct Translation_Data *translation_data,enum LEXER_TYPE kw)
{
	struct token *hold_token;
	if(token_ptr_has_remaining_tokens(translation_data->token_pointer))
	{
		hold_token=token_ptr_check_next_normal_token(translation_data->token_pointer);

		return hold_token->type==kw;
	}else
	{
		return 0;
	}
}
_Bool get_and_check(struct Translation_Data *translation_data,enum LEXER_TYPE kw)
{
	struct token *hold_token;
	if(!token_ptr_has_remaining_tokens(translation_data->token_pointer))
	{
		return 0;
	}else
	{
		hold_token=token_ptr_check_next_normal_token(translation_data->token_pointer);
		if(hold_token->type!=kw)
		{
			return 0;
		}else
		{
			(void)get_next_token(translation_data);
			return 1;
		}
	}
}
_Bool get_and_check_unsafe(struct Translation_Data *translation_data,enum LEXER_TYPE kw)
{
	return get_and_check(translation_data,kw);
}
void chomp(struct Translation_Data *translation_data)
{
	(void)get_next_token(translation_data);
}

enum LEXER_TYPE kw_get(struct Translation_Data *translation_data)
{
	struct token *hold_token;
	if(!token_ptr_has_remaining_tokens(translation_data->token_pointer))
	{
		return LT_ERROR;
	}else
	{
		hold_token=token_ptr_check_next_normal_token(translation_data->token_pointer);
		return hold_token->type;
	}

}
struct token* get_next_token(struct Translation_Data *translation_data)
{
	return token_ptr_get_token_under_pointer(translation_data->token_pointer);
}
_Bool translation_eof(struct Translation_Data *translation_data)
{
	return !token_ptr_has_remaining_tokens(translation_data->token_pointer);
}
#endif