#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