WONKY



LOG | FILES | OVERVIEW


#ifndef WONKY_DEBUG_AST_C
#define WONKY_DEBUG_AST_C WONKY_DEBUG_AST_C
#include <debug_ast.h>

typedef _Bool (*debug_ast_function_ptr)(void*);


static debug_ast_function_ptr debug_ast_vector[AST_TYPE_END+1]=
{
	[OP_COMMA]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_ADDITION]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_POINTER_ADDITION]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_SUBTRACTION]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_MUL]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_DIV]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_REMAINDER]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_COND]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_FUNCTION]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_ADD_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_SUBTRACT_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_MULTIPLY_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_REMAINDER_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_DIV_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_SHIFT_RIGHT_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_SHIFT_LEFT_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_AND_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_XOR_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_PIPE_ASSIGN]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_NOP]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_LOGICAL_OR]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_LOGICAL_AND]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_LOGICAL_NOT]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_BITWISE_OR]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_BITWISE_AND]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_BITWISE_XOR]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_BITWISE_NOT]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_ADDR_OF]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_DEREFERENCE]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_MEMBER_TROUGH_PTR]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_MEMBER]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_ARR_SUBSCRIPT]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_POSTFIX_INC]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_POSTFIX_DEC]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_PREFIX_INC]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_PREFIX_DEC]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_UNARY_PLUS]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_UNARY_MINUS]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_CAST]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_SIZEOF]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_SHIFT_LEFT]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_SHIFT_RIGHT]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_LESS_EQ]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_GREATER_EQ]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_LESS]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_GREATER]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_EQUAL]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_NOT_EQUAL]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_DESIGNATOR]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_CONSTANT]=(debug_ast_function_ptr)is_valid_ast_expression,
	[OP_STRING_LITERAL]=(debug_ast_function_ptr)is_valid_ast_expression,
	[ST_COMPOUND]=(debug_ast_function_ptr)is_valid_compound_statement,
	[ST_EXPRESSION]=(debug_ast_function_ptr)is_valid_ast_expression,
	[ST_SWITCH]=(debug_ast_function_ptr)is_valid_switch_statement,
	[ST_IF]=(debug_ast_function_ptr)is_valid_if_statement,
	[ST_WHILE]=(debug_ast_function_ptr)is_valid_while_statement,
	[ST_DO_WHILE]=(debug_ast_function_ptr)is_valid_do_while_statement,
	[ST_GOTO]=(debug_ast_function_ptr)is_valid_goto_statement,
	[ST_LABEL]=(debug_ast_function_ptr)is_valid_labeled_statement,
	[ST_CASE]=(debug_ast_function_ptr)is_valid_case_statement,
	[ST_DEFAULT]=(debug_ast_function_ptr)is_valid_default_statement,
	[ST_CONTINUE]=(debug_ast_function_ptr)is_valid_break_continue_statement,
	[ST_BREAK]=(debug_ast_function_ptr)is_valid_break_continue_statement,
	[ST_RETURN]=(debug_ast_function_ptr)is_valid_return_statement,
	[ST_FOR]=(debug_ast_function_ptr)is_valid_for_statement,
	[ST_OBJECT_DECLARATION]=(debug_ast_function_ptr)is_valid_object_declaration,
	[ST_TYPE_DEFINITION]=(debug_ast_function_ptr)is_valid_type_definition,
	[ST_FUNCTION_DEFINITION]=(debug_ast_function_ptr)is_valid_function_definition,
	[ST_FUNCTION_DECLARATION]=(debug_ast_function_ptr)is_valid_function_declaration,
	[TRANSLATION_UNIT]=(debug_ast_function_ptr)is_valid_translation_unit,
	[ERROR_DECLARATION]=(debug_ast_function_ptr)is_valid_ast_error_declaration,
	[ERROR]=(debug_ast_function_ptr)is_valid_ast_error,
};

_Bool is_valid_ast_enum(enum AST_Type ast_type)
{
	return ast_type>=0 && ast_type<AST_TYPE_END;
}
_Bool is_valid_ast_expression_enum(enum AST_Type ast_type)
{
	return (ast_type>AST_TYPE_EXPRESSION_START && ast_type<AST_TYPE_EXPRESSION_END) || ast_type==ERROR;
}
_Bool is_valid_ast(struct AST *ast)
{
	if(ast==NULL || !is_valid_ast_enum(ast->type) || debug_ast_vector[ast->type]==NULL)
		return 0;
	else
		return debug_ast_vector[ast->type](ast);
}

_Bool is_valid_ast_expression(struct AST_Expression *expression)
{
	if(expression==NULL || !is_valid_ast_expression_enum(expression->type))
		return 0;
	else
		return 1;
}
_Bool is_valid_ast_error(struct AST_Error *error)
{
	if(error==NULL || error->type!=ERROR)
	{
		return 0;
	}else
	{
		if(error->error==NULL || is_valid_ast(error->error))
			return 1;
		else
			return 0;
	}
}
_Bool is_valid_ast_error_declaration(struct AST_Declaration_Error *error)
{
	if(error==NULL || error->type!=ERROR_DECLARATION)
		return 0;
	else
	{
		if(error->error==NULL || is_valid_denoted(error->error))
			return 1;
		else
			return 0;
	}

}
_Bool is_valid_binary_expression(struct AST_Binary_Expression *expression)
{
	if(expression==NULL || !is_valid_ast_expression_enum(expression->type))
		return 0;
	else
	{
		return 	is_valid_value(expression->value)
			&&
			is_valid_ast_expression(expression->left)
			&&
			is_valid_ast_expression(expression->right)
		;
	}
}
_Bool is_valid_pointer_addition_expression(struct AST_Pointer_Addition_Expression *addition)
{
	if(addition==NULL || addition->type!=OP_POINTER_ADDITION)
		return 0;
	else
	{
		return 	is_valid_value(addition->value)
			&&
			is_valid_ast_expression(addition->pointer)
			&&
			is_valid_ast_expression(addition->integer)
		;
	}
}
_Bool is_valid_conditional_expression(struct AST_Conditional_Expression *conditional_expression)
{
	if(conditional_expression==NULL || conditional_expression->type!=OP_COND)
		return 0;
	else
	{
		return 	is_valid_value(conditional_expression->value)
			&&
			is_valid_ast_expression(conditional_expression->left)
			&&
			is_valid_ast_expression(conditional_expression->center)
			&&
			is_valid_ast_expression(conditional_expression->right)
		;
	}
}
_Bool is_valid_function_expression(struct AST_Function_Expression *function_call)
{
	if(function_call==NULL || function_call->type!=OP_FUNCTION)
		return 0;
	else if(!is_valid_ast_expression(function_call->id) || !is_valid_value(function_call->value))
		return 0;
	else
	{
		size_t i;
		for(i=0;i<function_call->number_of_arguments;++i)
			if(!is_valid_ast_expression(function_call->arg_list[i]))
				return 0;
		return 1;
	}
}
_Bool is_valid_ast_constant(struct AST_Constant *constant)
{
	if(constant==NULL || constant->type!=OP_CONSTANT)
		return 0;
	else
		return 1;
}
_Bool is_valid_ast_string_literal(struct AST_String_Literal *literal)
{
	if(literal==NULL || literal->type!=OP_STRING_LITERAL)
		return 0;
	else
		return 1;
}
_Bool is_valid_ast_designator(struct AST_Designator *designator)
{
	if(designator==NULL || designator->type!=OP_DESIGNATOR)
		return 0;
	else
	       	return 	is_valid_value(designator->value)
			&&
			is_valid_id(designator->id)
			;
}
_Bool is_valid_unary_expression(struct AST_Unary_Expression *expression)
{
	static _Bool unary_expressions[AST_TYPE_END]
			=
			{
				[OP_CAST]=1,
				[OP_DEREFERENCE]=1,
				[OP_ADDR_OF]=1,
				[OP_SIZEOF]=1,
				[OP_PREFIX_INC]=1,
				[OP_PREFIX_DEC]=1,
				[OP_POSTFIX_INC]=1,
				[OP_POSTFIX_DEC]=1,
				[OP_UNARY_PLUS]=1,
				[OP_UNARY_MINUS]=1,
				[OP_BITWISE_NOT]=1,
				[OP_LOGICAL_NOT]=1,
			};

	if(expression==NULL || !is_valid_expression_value_type(expression->type) || !unary_expressions[expression->type])
		return 0;
	else
	       	return is_valid_value(expression->value) && is_valid_ast_expression(expression->operand);
}
_Bool is_valid_labeled_statement(struct AST_Labeled_Statement *statement)
{
	if(statement==NULL || !is_valid_ast_enum(statement->type))
		return 0;
	else
		return is_valid_denoted_statement(statement->label);
}
_Bool is_valid_case_statement(struct AST_Case_Statement *statement)
{
	if(statement==NULL || !is_valid_ast_enum(statement->type))
		return 0;
	else
		return is_valid_ast(statement->statement) && is_valid_ast_expression(statement->control);
}
_Bool is_valid_default_statement(struct AST_Default_Statement *statement)
{
	if(statement==NULL || !is_valid_ast_enum(statement->type))
		return 0;
	else
		return is_valid_ast(statement->statement);
}
_Bool is_valid_break_continue_statement(struct AST_Break_Continue_Statement *statement)
{
	if(statement==NULL || !is_valid_ast_enum(statement->type))
		return 0;
	else
		return statement->parent!=NULL;  /*we don't check parent*/
}
_Bool is_valid_compound_statement(struct AST_Compound_Statement *statement)
{
	if(statement==NULL || !is_valid_ast_enum(statement->type))
		return 0;
	else
	{
		struct Queue_Node *it;
		for(it=statement->components->first;it!=NULL;it=it->prev)
			if(!is_valid_ast(it->data))
				return 0;

		return statement->scope!=NULL;
	}
}
_Bool is_valid_for_statement(struct AST_For_Statement *statement)
{
	if(statement==NULL || !is_valid_ast_enum(statement->type))
		return 0;
	else
	{
		return 	is_valid_ast(statement->condition)
			&&
			is_valid_ast(statement->initialisation)
			&&
			is_valid_ast(statement->update)
			&&
			is_valid_ast(statement->body_statement)
			;
	}
}
_Bool is_valid_while_statement(struct AST_While_Statement *statement)
{
	if(statement==NULL || !is_valid_ast_enum(statement->type))
		return 0;
	else
	{
		return 	is_valid_ast(statement->condition)
			&&
			is_valid_ast(statement->body_statement)
			;
	}
}
_Bool is_valid_do_while_statement(struct AST_Do_While_Statement *statement)
{
	if(statement==NULL || statement->type!=ST_DO_WHILE)
		return 0;
	else
	{
		return 	is_valid_ast(statement->condition)
			&&
			is_valid_ast(statement->body_statement)
			;
	}
}
_Bool is_valid_if_statement(struct AST_If_Statement *statement)
{
	if(statement==NULL || !is_valid_ast_enum(statement->type))
		return 0;
	else
	{
		if(statement->else_statement!=NULL && !is_valid_ast(statement->else_statement))
			return 0;
		else
			return 	is_valid_ast(statement->condition)
				&&
				is_valid_ast(statement->body_statement)
				;
	}
}
_Bool is_valid_goto_statement(struct AST_Goto_Statement *statement)
{
	if(statement==NULL || !is_valid_ast_enum(statement->type))
		return 0;
	else
	{
		if(statement->label!=NULL && !is_valid_denoted_statement(statement->label))
			return 0;
		if(statement->previous_denoted_object!=NULL && !is_valid_denoted_object(statement->previous_denoted_object))
			return 0;
		return 1;
	}
}
_Bool is_valid_switch_statement(struct AST_Switch_Statement *statement)
{
	if(statement==NULL || !is_valid_ast_enum(statement->type))
		return 0;
	else
	{
		return 	is_valid_ast_expression(statement->condition)
			&&
			is_valid_ast(statement->body_statement);
	}
}
_Bool is_valid_return_statement(struct AST_Return_Statement *statement)
{
	if(statement==NULL || !is_valid_ast_enum(statement->type))
		return 0;
	else
		return is_valid_ast(statement->return_expression);
}
_Bool is_valid_type_definition(struct AST_Type_Definition *definition)
{
	if(definition==NULL || !is_valid_ast_enum(definition->type))
		return 0;
	else
		return is_valid_denoted_type(definition->definition);
}
_Bool is_valid_object_declaration(struct AST_Object_Declaration *declaration)
{
	if(declaration==NULL || !is_valid_ast_enum(declaration->type))
		return 0;
	else
		return is_valid_denoted_object(declaration->object) && is_valid_initialiser(declaration->initializer);
}
_Bool is_valid_function_definition(struct AST_Function_Definition *definition)
{
	if(definition==NULL || !is_valid_ast_enum(definition->type))
		return 0;
	else
		return is_valid_denoted_function(definition->function) && is_valid_compound_statement(definition->body);
}
_Bool is_valid_function_declaration(struct AST_Function_Declaration *declaration)
{
	if(declaration==NULL || !is_valid_ast_enum(declaration->type))
		return 0;
	else
		return is_valid_denoted_function(declaration->function);
}
_Bool is_valid_translation_unit(struct AST_Translation_Unit *unit)
{
	if(unit==NULL || !is_valid_ast_enum(unit->type))
		return 0;
	else
	{
		struct Queue_Node *it;
		for(it=unit->function_definitions->first;it!=NULL;it=it->prev)
			if(!is_valid_ast(it->data))
				return 0;

		if(!is_valid_scope(unit->file_scope))
			return 0;

		if(!is_valid_linkage(unit->internal_linkage))
			return 0;

		return 1;
	}
}
#endif