WONKY



LOG | FILES | OVERVIEW


#ifndef WONKY_AST_C
#define WONKY_AST_C WONKY_AST_C
#include <ast.h>

struct AST_Error* get_error_tree(struct AST *error)
{
	struct AST_Error *ret;
	ret=wonky_malloc(sizeof(struct AST_Error));
	ret->type=ERROR;
	ret->error=error;
	return ret;
}
struct AST_Declaration_Error* get_declaration_error_tree(struct Denoted *error)
{

	struct AST_Declaration_Error *ret;
	ret=wonky_malloc(sizeof(struct AST_Declaration_Error));
	ret->type=ERROR_DECLARATION;
	ret->error=error;
	return ret;
}
/*if an int can represent all the values of the original type the value is converted to int
 * otherwise to unsigned int. other types are untouched
 * 6.3.1.1 */
struct AST_Expression* get_promoted_expression(struct AST_Expression *operand,struct Translation_Data *translation_data)
{
	struct Type *operand_type;
	struct Type *promotion_type;

	operand_type=extract_expresion_value_type(operand->value);
	promotion_type=get_type_for_promotion(operand_type);
	if(!types_are_identical(operand_type,promotion_type))
		return get_cast_expression_tree(operand,promotion_type,translation_data);
	else
		return operand;
}

struct AST_Expression* get_promoted_expression_for_function_call(struct AST_Expression *operand,struct Translation_Data *translation_data)
{
	struct Type *operand_type;

	if(operand->type==ERROR)
		return operand;

	operand_type=extract_expresion_value_type(operand->value);
	if(operand_type->specifier==TS_FLOAT)
	{
		return get_cast_expression_tree(operand,(struct Type*)get_type_insecure(TS_DOUBLE,TSIGN_NONE,TC_NONE,DOUBLE_SIZE),translation_data);
	}else
	{
		return get_promoted_expression(operand,translation_data);
	}
}

struct AST_Expression* get_cast_expression_tree(struct AST_Expression *operand,struct Type *type,struct Translation_Data *translation_data)
{
	struct Type *operand_type;
	if(!type_is_scalar(type) || operand->type==ERROR)
	{
	       	push_translation_error("cast type needs to be of scalar type",translation_data);
		push_translation_note("got %T instead",translation_data,type);

		return (struct AST_Expression*)get_error_tree((struct AST*)get_unary_expression_tree(
						operand,
						get_expression_value_rvalue(get_temp_object(type)),
						OP_CAST
				));
	}else
	{

		operand_type=extract_expresion_value_type(operand->value);
		if(types_are_identical(operand_type,type))
			return operand;

		return (struct AST_Expression*)	get_unary_expression_tree(
						operand,
						get_expression_value_rvalue(get_temp_object(type)),
						OP_CAST
				);
	}
}
struct AST_Expression* get_degraded_array_expression_if_it_has_the_right_type(struct AST_Expression *expression,struct Translation_Data *translation_data)
{
	struct Type *expression_type;
	struct Type_Array *array_type;

	if(expression->type==ERROR)
		return expression;

	expression_type=extract_expresion_value_type(expression->value);
	if(expression_type->specifier==TS_ARRAY)
	{
		array_type=(struct Type_Array*)expression_type;
		expression_type=get_pointer_type(array_type->is_array_of,1,0);

		wonky_assert(expression_type!=NULL);

		return get_cast_expression_tree(expression,expression_type,translation_data);
	}else
	{
		return expression;
	}
}

/* 
 * it finds the common real type of the operands then 'upgrades' them
 * realise the usual arithmetic conversions in 6.3.1.8
 * */
struct AST_Binary_Expression* get_binary_expression_after_conversion(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type type,struct Translation_Data *translation_data)
{
	struct Type_Basic *left_type;
	struct Type_Basic *right_type;
	struct Expression_Value *value;

	left=get_degraded_array_expression_if_it_has_the_right_type(left,translation_data);
	right=get_degraded_array_expression_if_it_has_the_right_type(right,translation_data);

	left=get_promoted_expression(left,translation_data);
	right=get_promoted_expression(right,translation_data);

	left_type=(struct Type_Basic*)extract_expresion_value_type(left->value);
	right_type=(struct Type_Basic*)extract_expresion_value_type(right->value);

	if(left_type->specifier==TS_DOUBLE)
	{
		if(right_type->specifier==TS_DOUBLE && right_type->constraint==TC_LONG)
			left=get_cast_expression_tree(left,(struct Type*)right_type,translation_data);
		else
			right=get_cast_expression_tree(right,(struct Type*)left_type,translation_data);
	
	}else if(right_type->specifier==TS_DOUBLE)
	{
		if(left_type->specifier==TS_DOUBLE && left_type->constraint==TC_LONG)
			right=get_cast_expression_tree(right,(struct Type*)left_type,translation_data);
		else
			left=get_cast_expression_tree(left,(struct Type*)right_type,translation_data);
	}else if(left_type->specifier==TS_FLOAT)
	{
		right=get_cast_expression_tree(right,(struct Type*)left_type,translation_data);
	}else if(right_type->specifier==TS_FLOAT)
	{
		left=get_cast_expression_tree(left,(struct Type*)right_type,translation_data);
	}else if(type_is_arithmetic((struct Type*)left_type) && type_is_arithmetic((struct Type*)right_type) && !types_are_identical((struct Type*)left_type,(struct Type*)right_type))
	{
		/*should have integers by now*/
		int left_rank;
		int right_rank;
		struct Type_Basic *greater_type;


		left_rank=type_get_integer_conversion_rank(left_type);
		right_rank=type_get_integer_conversion_rank(right_type);

		if(left_type->sign==TSIGN_SIGNED)
		{
			if(right_type->sign==TSIGN_SIGNED || left_rank!=right_rank)
				greater_type=(left_rank<right_rank?right_type:left_type);	
			else 
				greater_type=get_type_insecure(left_type->specifier,TSIGN_UNSIGNED,left_type->constraint,left_type->size);
		}
		else
		{
			if(right_type->sign==TSIGN_UNSIGNED || left_rank!=right_rank)
				greater_type=(left_rank<right_rank?right_type:left_type);	
			else 
				greater_type=get_type_insecure(right_type->specifier,TSIGN_UNSIGNED,right_type->constraint,right_type->size);
		}
		
		left=get_cast_expression_tree(left,(struct Type*)greater_type,translation_data);
		right=get_cast_expression_tree(right,(struct Type*)greater_type,translation_data);
	}
		
	value=get_expression_value_rvalue(get_temp_object((struct Type*)extract_expresion_value_type(left->value)));
	return get_binary_expression_tree(left,right,value,type);
}

/*TODO remove this*/
struct AST_Binary_Expression* get_binary_expression_tree(struct AST_Expression *left,struct AST_Expression *right,struct Expression_Value *value,enum AST_Type type)
{
	struct AST_Binary_Expression *ret;
	ret=wonky_malloc(sizeof(struct AST_Binary_Expression));
	ret->type=type;
	ret->left=left;
	ret->right=right;
	ret->value=value;

	return ret;
}

struct AST_Binary_Expression* get_modulo_tree(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data)
{
	if(constraint_check_modulo_expression(left,right,translation_data))
	{
		return get_binary_expression_after_conversion(left,right,OP_REMAINDER,translation_data);
	}else
	{
		return (struct AST_Binary_Expression*) get_error_tree((struct AST*)get_binary_expression_tree(left,right,NULL,OP_REMAINDER));
	}
}
struct AST_Binary_Expression* get_multiplicative_expression_tree(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)
{
	if(constraint_check_multiplicative_expression(left,right,operation,translation_data))
	{
		return get_binary_expression_after_conversion(left,right,operation,translation_data);
	}else
	{
		return (struct AST_Binary_Expression*) get_error_tree((struct AST*)get_binary_expression_tree(left,right,NULL,operation));
	}
}
struct AST_Binary_Expression* get_additive_expression_tree(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)
{
	if(constraint_check_additive_expression(left,right,operation,translation_data))
	{
		return get_binary_expression_after_conversion(left,right,operation,translation_data);
	}else
	{
		return (struct AST_Binary_Expression*) get_error_tree((struct AST*)get_binary_expression_tree(left,right,NULL,operation));
	}
}
struct AST_Binary_Expression* get_shift_expression_tree(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)
{
	if(constraint_check_shift_expression(left,right,operation,translation_data))
	{
		return get_binary_expression_tree(left,right,get_expression_value_rvalue(get_temp_object(extract_expresion_value_type(left->value))),operation);
	}else
	{
		return (struct AST_Binary_Expression*) get_error_tree((struct AST*)get_binary_expression_tree(left,right,NULL,operation));
	}
}
struct AST_Binary_Expression* get_bitwise_expression_tree(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)
{
	if(constraint_check_bitwise_expression(left,right,operation,translation_data))
	{
		return get_binary_expression_after_conversion(left,right,operation,translation_data);
	}else
	{
		return (struct AST_Binary_Expression*) get_error_tree((struct AST*)get_binary_expression_tree(left,right,NULL,operation));
	}
}

struct AST_Binary_Expression* get_relation_expression_tree(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)
{
	if(constraint_check_relational_operation(left,right,operation,translation_data))
	{
		return get_binary_expression_tree(left,right,get_expression_value_rvalue(get_temp_object((struct Type*)get_type_insecure(TS_INT,TSIGN_SIGNED,TC_NONE,INT_SIZE))),operation);
	}else
	{
		return (struct AST_Binary_Expression*) get_error_tree((struct AST*)get_binary_expression_tree(left,right,NULL,operation));
	}
}
struct AST_Binary_Expression* get_equality_expression_tree(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)
{
	if(constraint_check_equality_expression(left,right,translation_data))
	{
		return get_binary_expression_tree(left,right,get_expression_value_rvalue(get_temp_object((struct Type*)get_type_insecure(TS_INT,TSIGN_SIGNED,TC_NONE,INT_SIZE))),operation);
	}else
	{
		return (struct AST_Binary_Expression*) get_error_tree((struct AST*)get_binary_expression_tree(left,right,NULL,operation));
	}
}
struct AST_Binary_Expression* get_logical_expression_tree(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)
{
	return get_binary_expression_tree(left,right,get_expression_value_rvalue(get_temp_object((struct Type*)get_type_insecure(TS_INT,TSIGN_SIGNED,TC_NONE,INT_SIZE))),operation);
}

struct AST_Binary_Expression* get_simple_assignment_expression_tree(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data)
{

	if(constraint_check_simple_assignment_expression(left,right,translation_data))
	{
		struct Type *left_type;

		left_type=extract_expresion_value_type(left->value);

		left_type=get_unqualified_version_of_type(left_type);

		right=get_cast_expression_tree(right,left_type,translation_data);

		return get_binary_expression_tree(left,right,get_expression_value_rvalue(get_temp_object(left_type)),OP_ASSIGN);
	}else
	{
		return (struct AST_Binary_Expression*) get_error_tree((struct AST*)get_binary_expression_tree(left,right,NULL,OP_ASSIGN));
	}
}

struct AST_Binary_Expression* get_compound_assignment_expression_tree(struct AST_Expression *left,struct AST_Expression *right,enum AST_Type operation,struct Translation_Data *translation_data)
{
	if(constraint_check_compound_assignment_expression(left,right,operation,translation_data))
	{
		struct Type *left_type;
		left_type=extract_expresion_value_type(left->value);
		left_type=get_unqualified_version_of_type(left_type);

		right=get_cast_expression_tree(right,left_type,translation_data);
		return get_binary_expression_tree(left,right,get_expression_value_rvalue(get_temp_object(left_type)),operation);
	}else
	{
		return (struct AST_Binary_Expression*) get_error_tree((struct AST*)get_binary_expression_tree(left,right,NULL,OP_ASSIGN));
	}
}

struct AST_Binary_Expression* get_comma_expression_tree(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data)
{
	if(left->type!=ERROR && right->type!=ERROR)
	{
		return get_binary_expression_tree(left,right,get_expression_value_rvalue(get_temp_object((extract_expresion_value_type(right->value)))),OP_COMMA);
	}else
	{
		return get_binary_expression_tree(left,right,NULL,OP_COMMA);
	}
}

/*TODO right might be null if so then it's a [] array */
struct AST_Binary_Expression* get_array_subscript_tree(struct AST_Expression *left,struct AST_Expression *right,struct Translation_Data *translation_data)
{
	struct Type *left_type;
	struct Type *member_type;	

	left=get_degraded_array_expression_if_it_has_the_right_type(left,translation_data);
	right=get_degraded_array_expression_if_it_has_the_right_type(right,translation_data);

	left_type=extract_expresion_value_type(left->value);
	if(left_type->specifier!=TS_POINTER)
	{
		push_translation_error("Expected a pointer type in array subscript",translation_data);
		push_translation_note("Instead got %T",translation_data,left_type);

		return (struct AST_Binary_Expression*) get_error_tree((struct AST*)get_binary_expression_tree(left,right,NULL,OP_ARR_SUBSCRIPT));
	}

	member_type=((struct Type_Pointer*)left_type)->points_to;
	if(!type_is_of_object(member_type))
	{
		push_translation_error("expected pointer to object type in array subscript",translation_data);
		push_translation_note("Instead got %T",translation_data,member_type);

		return (struct AST_Binary_Expression*) get_error_tree((struct AST*)get_binary_expression_tree(left,right,NULL,OP_ARR_SUBSCRIPT));
	}

	return get_binary_expression_tree(left,right,get_expression_value_lvalue(get_temp_object(member_type)),OP_ARR_SUBSCRIPT);

}
struct AST_Binary_Expression* get_struct_union_member_tree(struct AST_Expression *left,struct identifier *id,struct Translation_Data *translation_data)
{
	struct AST_Binary_Expression *ret;
	struct Type_Struct_Union *left_type;



	if(!constraint_check_struct_union_member_expression(left,id,translation_data))
	{
		wonky_free(id);/*welp*/
		return (struct AST_Binary_Expression*)get_error_tree((struct AST*)left);
	}

	left_type=(struct Type_Struct_Union*)extract_expresion_value_type(left->value);

	wonky_assert(left_type->specifier==TS_STRUCT || left_type->specifier==TS_UNION);

	ret=wonky_malloc(sizeof(struct AST_Binary_Expression));
	ret->type=OP_MEMBER;

	ret->right=(struct AST_Expression*)get_struct_union_member_tree_designator(id,left_type->struct_union->inner_namespace,translation_data);
	ret->left=left;
	ret->value=ret->right->value; /*BEWARE*/

	
	if(ret->right->type==ERROR)
		return (struct AST_Binary_Expression *)get_error_tree((struct AST*)ret);
	else
		return ret;
}

/*TODO beware const type qualifier*/
struct AST_Binary_Expression* get_struct_union_member_trough_ptr_tree(struct AST_Expression *left,struct identifier *id,struct Translation_Data *translation_data)
{
	struct AST_Expression *hold_derefernced;
	hold_derefernced=(struct AST_Expression*)get_indirection_expression_tree(left,translation_data);
	if(hold_derefernced->type==ERROR)
		return (struct AST_Binary_Expression*)hold_derefernced;
	else
		return get_struct_union_member_tree(hold_derefernced,id,translation_data);
}

struct AST_Conditional_Expression* get_conditional_expression_tree(struct AST_Expression *left,struct AST_Expression *center,struct AST_Expression *right,struct Translation_Data *translation_data)
{
	struct AST_Conditional_Expression *ret;
	ret=wonky_malloc(sizeof(struct AST_Conditional_Expression));
	ret->type=OP_COND;
	ret->left=left;
	ret->center=center;
	ret->right=right;
	if(!constraint_check_conditional_expression(left,center,right,translation_data))
		return (struct AST_Conditional_Expression*)get_error_tree((struct AST*)ret);
	ret->value=get_expression_value_rvalue(get_temp_object(extract_expresion_value_type(center->value)));
	return ret;
}

struct AST_Function_Expression* get_function_expression_tree(struct AST_Expression *id,struct Queue *arg_list,struct Translation_Data *translation_data)
{

	struct AST_Function_Expression *ret;
	struct Type_Function *id_type;
	size_t i;

	if(id->type==ERROR)
	{
		while(arg_list->size>0)
			delete_ast(Queue_Pop(arg_list));
		return (struct AST_Function_Expression*)get_error_tree((struct AST*)id);
	}
	else 
	{
		id_type=(struct Type_Function*)extract_expresion_value_type(id->value);
		if(type_is_pointer_to_function((struct Type*)id_type))
			id_type=(struct Type_Function*)((struct Type_Pointer*)id_type)->points_to;
		else
			return (struct AST_Function_Expression*)get_error_tree((struct AST*)id);
	}

	ret=wonky_malloc(sizeof(struct AST_Function_Expression));
	ret->type=OP_FUNCTION;
	ret->value=NULL; /*So, we need to know if there is some error somewhere before we can begin extracting lvalue information*/
	ret->id=id;
	ret->number_of_arguments=arg_list->size;

	ret->arg_list=wonky_calloc(ret->number_of_arguments,sizeof(struct AST_Expression*));

	for(i=0;i<ret->number_of_arguments;++i)
	{
		wonky_assert(arg_list->size>0);
		if(i>=id_type->number_of_arguments)
			ret->arg_list[i]=get_promoted_expression_for_function_call((struct AST_Expression*)Queue_Pop(arg_list),translation_data);
		else
			ret->arg_list[i]=get_cast_expression_tree((struct AST_Expression*)Queue_Pop(arg_list),id_type->arguments[i]->object->type,translation_data);	
	}

	wonky_assert(arg_list->size==0);

	if(constraint_check_function_expression(ret,translation_data) && id->type!=ERROR && id_type->specifier!=TS_ERROR)	
	{
		ret->value=get_expression_value_rvalue(get_temp_object(id_type->return_type));
		return ret;
	}
	else
	{
		return (struct AST_Function_Expression*)get_error_tree((struct AST*)ret);
	}
}
struct AST_Unary_Expression* get_unary_expression_tree(struct AST_Expression *operand,struct Expression_Value *value,enum AST_Type type)
{

	struct AST_Unary_Expression *ret;
	ret=wonky_malloc(sizeof(struct AST_Unary_Expression));
	ret->operand=operand;
	ret->type=type;
	ret->value=value;

	return ret;
}

struct AST_Unary_Expression* get_indirection_expression_tree(struct AST_Expression *operand,struct Translation_Data *translation_data)
{
	struct AST_Unary_Expression *ret;
	struct Type_Pointer *operand_type;

	if(constraint_check_indirection_expression(operand,translation_data))
	{
		ret=wonky_malloc(sizeof(struct AST_Unary_Expression));
		ret->type=OP_DEREFERENCE;
		ret->operand=operand;
		operand_type=(struct Type_Pointer*)extract_expresion_value_type(operand->value);
		ret->value=get_expression_value_lvalue(get_temp_object(operand_type->points_to));

		return ret;
	}else
	{
		return operand->type==ERROR ? (struct AST_Unary_Expression*)operand : (struct AST_Unary_Expression*)get_error_tree((struct AST*)operand);
	}

}
struct AST_Unary_Expression* get_address_expression_tree(struct AST_Expression *operand,struct Translation_Data *translation_data)
{
	struct AST_Unary_Expression *ret;
	struct Type *operand_type;
	if(constraint_check_address_expression(operand,translation_data))
	{
		ret=wonky_malloc(sizeof(struct AST_Unary_Expression));
		ret->type=OP_ADDR_OF;
		ret->operand=operand;

		operand_type=extract_expresion_value_type(operand->value);
		ret->value=get_expression_value_rvalue(get_temp_object(get_pointer_type(operand_type,0,0)));

		return ret;
	}else
	{
		return operand->type==ERROR ? (struct AST_Unary_Expression*)operand : (struct AST_Unary_Expression*)get_error_tree((struct AST*)operand);
	}
}

struct AST_Unary_Expression* get_sizeof_by_type_tree(struct Type *type)
{
	return get_unary_expression_tree(NULL,get_expression_value_rvalue(get_temp_object(type)),OP_SIZEOF);
}


struct AST_Unary_Expression* get_unary_plus_minus_expression(struct AST_Expression *operand,enum AST_Type operation,struct Translation_Data *translation_data)
{
	struct Type *operand_type;
	if(constraint_check_unary_plus_minus(operand,operation,translation_data))
	{
		operand=get_promoted_expression(operand,translation_data);
		operand_type=extract_expresion_value_type(operand->value);
		return get_unary_expression_tree(operand,get_expression_value_rvalue(get_temp_object(operand_type)),operation);
	}else
	{
		return operand->type==ERROR ? (struct AST_Unary_Expression*)operand : (struct AST_Unary_Expression*)get_error_tree((struct AST*)operand);
	}
}
struct AST_Unary_Expression* get_unary_bitwise_not_expression(struct AST_Expression *operand,struct Translation_Data *translation_data)
{
	struct Type *operand_type;
	if(constraint_check_unary_bitwise_not(operand,translation_data))
	{
		operand=get_promoted_expression(operand,translation_data);
		operand_type=extract_expresion_value_type(operand->value);
		return get_unary_expression_tree(operand,get_expression_value_rvalue(get_temp_object(operand_type)),OP_BITWISE_NOT);
	}else
	{
		return operand->type==ERROR ? (struct AST_Unary_Expression*)operand : (struct AST_Unary_Expression*)get_error_tree((struct AST*)operand);
	}
}
struct AST_Unary_Expression* get_unary_logical_not_expression(struct AST_Expression *operand,struct Translation_Data *translation_data)
{
	struct Type *operand_type;
	if(constraint_check_unary_logical_not(operand,translation_data))
	{
		operand=get_promoted_expression(operand,translation_data);
		operand_type=extract_expresion_value_type(operand->value);
		return get_unary_expression_tree(operand,get_expression_value_rvalue(get_temp_object(operand_type)),OP_LOGICAL_NOT);
	}else
	{
		return operand->type==ERROR ? (struct AST_Unary_Expression*)operand : (struct AST_Unary_Expression*)get_error_tree((struct AST*)operand);
	}
}

struct AST_Unary_Expression* get_postfix_inc_dec_tree(struct AST_Expression *operand,enum AST_Type operation,struct Translation_Data *translation_data)
{
	struct Type *operand_type;
	operand=get_degraded_array_expression_if_it_has_the_right_type(operand,translation_data);
	operand_type=extract_expresion_value_type(operand->value);
	if(constraint_check_postfix_inc_dec_expression(operand,operation,translation_data))
	{
		return get_unary_expression_tree(operand,get_expression_value_rvalue(get_temp_object(operand_type)),operation); /*TODO return expression value rvaluesness is under question*/
	}else
	{
		return operand->type==ERROR ? (struct AST_Unary_Expression*)operand : (struct AST_Unary_Expression*)get_error_tree((struct AST*)operand);
	}
}
struct AST_Unary_Expression* get_prefix_inc_dec_tree(struct AST_Expression *operand,enum AST_Type operation,struct Translation_Data *translation_data)
{
	struct Type *operand_type;

	if(operand->type==ERROR)
		return (struct AST_Unary_Expression*)operand;
	
	operand=get_degraded_array_expression_if_it_has_the_right_type(operand,translation_data);
	operand_type=extract_expresion_value_type(operand->value);
	if(constraint_check_prefix_inc_dec_expression(operand,operation,translation_data))
	{
		return get_unary_expression_tree(operand,get_expression_value_rvalue(get_temp_object(operand_type)),operation); /*TODO return expression value rvaluesness is under question*/
	}else
	{
		return operand->type==ERROR ? (struct AST_Unary_Expression*)operand : (struct AST_Unary_Expression*)get_error_tree((struct AST*)operand);
	}

}
struct AST_Unary_Expression* get_unary_sizeof_tree(struct AST_Expression *operand,struct Translation_Data *translation_data)
{
	return (struct AST_Unary_Expression*)get_error_tree(NULL);
}
struct AST_Constant* get_constant_tree(struct Expression_Value_Constant *value)
{
	struct AST_Constant *ret;
	ret=wonky_malloc(sizeof(struct AST_Constant));
	ret->type=OP_CONSTANT;
	ret->value=value;
	return ret;

}
struct AST_String_Literal* get_string_literal_tree(struct Expression_Value_Constant *value)
{
	struct AST_String_Literal *ret;
	ret=wonky_malloc(sizeof(struct AST_Constant));
	ret->type=OP_STRING_LITERAL;
	ret->value=value;
	return ret;

}
struct AST_Expression* get_designator_tree(struct token_identifier *id,struct Scope* scope,struct Translation_Data *translation_data)
{
	struct AST_Designator *ret;
	struct Denoted *hold_denoted;


	ret=wonky_malloc(sizeof(struct AST_Designator));
	ret->type=OP_DESIGNATOR;


	hold_denoted=check_ordinary(scope,id->id);
	if(hold_denoted==NULL)
	{
		push_translation_error("using undeclared id - %WI\n%WSl \"%Wtl\"",translation_data,id->id,id->delta->location,id);
		wonky_free(ret);
		return (struct AST_Expression*)get_error_tree(NULL);
	}else
	{
		switch(hold_denoted->denotation)
		{
			case DT_Enum_Constant:
				ret->value=(struct Expression_Value*)get_expression_value_constant(extract_enum_constant((struct Denoted_Enum_Const*)hold_denoted));
				break;
			case DT_Object:
				ret->value=get_expression_value_lvalue( ((struct Denoted_Object*)hold_denoted)->object );
				break;
			case DT_Function:
				ret->value=get_expression_value_function_designator((struct Denoted_Function*)hold_denoted);
				ret->id=id->id;
				return (struct AST_Expression*)get_address_expression_tree((struct AST_Expression*)ret,translation_data);/*BEWARE*/
		}
	}

	ret->id=id->id;
	return (struct AST_Expression*)ret;
}

struct AST_Designator* get_designator_tree_from_denoted_object(struct Denoted_Object *object,struct Translation_Data *translation_data)
{
	struct AST_Designator *ret;
	ret=wonky_malloc(sizeof(struct AST_Designator));
	ret->type=OP_DESIGNATOR;
	ret->value=get_expression_value_lvalue(object->object);
	ret->id=object->id;


	return ret;
}
struct AST_Designator* get_struct_union_member_tree_designator(struct identifier *id,struct Normal_Scope *inner_scope,struct Translation_Data *translation_data)
{
	struct AST_Designator *ret;
	struct Denoted *hold_denoted;


	ret=wonky_malloc(sizeof(struct AST_Designator));
	ret->type=OP_DESIGNATOR;


	hold_denoted=check_struct_union_member(inner_scope,id);



	if(hold_denoted==NULL)
	{
		push_translation_error("%t is not a member of the structure",translation_data,id);
		wonky_free(ret);
		return (struct AST_Designator*)get_error_tree(NULL);
	}else
	{
		ret->value=get_expression_value_lvalue( ((struct Denoted_Object*)hold_denoted)->object );
	}

	ret->id=id;
	return ret;
}

struct AST_Case_Statement* get_case_statement_tree(struct AST *statement,struct AST_Expression *control,struct AST_Switch_Statement *parent,struct Translation_Data *translation_data)
{
	struct AST_Case_Statement *ret;
	ret=wonky_malloc(sizeof(struct AST_Case_Statement));

	ret->type=ST_CASE;
	ret->control=control;
	ret->statement=statement;

	if(constraint_check_case_statement(ret,parent,translation_data))
		return ret;
	else
		return (struct AST_Case_Statement*)get_error_tree((struct AST*)ret);

}
struct AST_Labeled_Statement* get_labeled_statement_tree(struct identifier *label,struct AST* statement,enum AST_Type type,struct Translation_Data *translation_data,struct Scope *scope)
{
	struct AST_Labeled_Statement *ret;
	ret=wonky_malloc(sizeof(struct AST_Labeled_Statement));
	ret->type=type;
	ret->label=(struct Denoted_Statement*)push_label(scope,label,statement,translation_data);
	return ret;
}
struct AST_Default_Statement* get_default_statement_tree(struct AST *statement,struct Translation_Data *translation_data)
{
	struct AST_Default_Statement *ret;
	ret=wonky_malloc(sizeof(struct AST_Default_Statement));
	ret->type=ST_DEFAULT;
	ret->statement=statement;

	return ret;
}
struct AST_Break_Continue_Statement* get_break_continue_statement_tree(struct AST *parent,struct Translation_Data *translation_data,enum AST_Type break_or_continue)
{
	struct AST_Break_Continue_Statement *ret;
	ret=wonky_malloc(sizeof(struct AST_Break_Continue_Statement));
	ret->type=break_or_continue;
	ret->parent=parent;
	if(constraint_check_break_continue_statement(ret,translation_data))
		return ret;
	else
		return (struct AST_Break_Continue_Statement*)get_error_tree((struct AST*)ret);
}
struct AST_Compound_Statement* get_compound_statement_tree(struct Scope *parent_scope)
{
	struct AST_Compound_Statement *ret;


	ret=wonky_malloc(sizeof(struct AST_Compound_Statement));
	ret->components=wonky_malloc(sizeof(struct Queue));

	ret->type=ST_COMPOUND;

	Queue_Init(ret->components);

	ret->scope=get_normal_scope(get_partial_normal_scope((struct Normal_Scope*)parent_scope),BLOCK_SCOPE);
	return ret;
}
struct AST_If_Statement* get_if_statement_tree()
{
	struct AST_If_Statement *ret;
	ret=wonky_malloc(sizeof(struct AST_If_Statement));
	ret->type=ST_IF;

	return ret;
}
struct AST_Switch_Statement* get_switch_statement_tree(struct AST_Expression *condidion,struct AST *body_statement)
{
	struct AST_Switch_Statement *ret;

	ret=wonky_malloc(sizeof(struct AST_Switch_Statement));
	ret->cases=wonky_malloc(sizeof(struct Queue));

	Queue_Init(ret->cases);

	ret->type=ST_SWITCH;
	ret->condition=condidion;
	ret->body_statement=body_statement;

	

	return ret;
}
struct AST_While_Statement* get_while_statement_tree()
{
	struct AST_While_Statement *ret;
	ret=wonky_malloc(sizeof(struct AST_While_Statement));
	ret->type=ST_WHILE;
	return ret;
}
struct AST_Do_While_Statement* get_do_while_statement_tree()
{
	struct AST_Do_While_Statement *ret;
	ret=wonky_malloc(sizeof(struct AST_Do_While_Statement));
	ret->type=ST_DO_WHILE;
	return ret;
}

struct AST_For_Statement* get_for_statement_tree()
{
	struct AST_For_Statement *ret;
	ret=wonky_malloc(sizeof(struct AST_For_Statement));
	ret->type=ST_FOR;
	return ret;
}
struct AST_Return_Statement* get_return_statement_tree(struct AST* return_expression,struct Translation_Data *translation_data,struct Scope *scope)
{
	struct AST_Return_Statement *ret;
	struct Denoted_Function *hold_function;
	struct Type *return_type;

	wonky_assert(is_valid_normal_scope((struct Normal_Scope*)scope));

	hold_function=get_enclosing_function(scope);
	return_type=((struct Type_Function*)hold_function->type)->return_type;

#warning does not seem to work with nop "return;"
	if(constraint_check_return_statement(return_expression,return_type,translation_data))
	{
		ret=wonky_malloc(sizeof(struct AST_If_Statement));
		ret->type=ST_RETURN;
		ret->checkpoint=get_partial_normal_scope((struct Normal_Scope*)scope);

		if(return_expression==NULL)
			ret->return_expression=NULL;
		else
			ret->return_expression=(struct AST*)get_cast_expression_tree((struct AST_Expression*)return_expression,return_type,translation_data);

		wonky_assert(is_valid_return_statement(ret));
		return ret;
	}else
	{
		return (struct AST_Return_Statement*)get_error_tree(return_expression);
	}
}

struct AST_Goto_Statement* get_goto_statement_tree(struct identifier *label,struct Scope *scope,struct Translation_Data *translation_data)
{
	struct AST_Goto_Statement *ret;
	struct Denoted_Statement *hold_statement;

	ret=wonky_malloc(sizeof(struct AST_Goto_Statement));
	ret->type=ST_GOTO;

	hold_statement=check_label(scope,label);
	if(hold_statement==NULL)
	{
		push_label(scope,label,NULL,translation_data);
		hold_statement=check_label(scope,label);
	}

	ret->label=hold_statement;

	Queue_Push(hold_statement->gotos_jumping_to_this_statement,ret);

	ret->previous_denoted_object=(struct Denoted_Object*)get_last_known_denoted_object((struct Normal_Scope*)scope);
	return ret;
}


struct AST* get_nop_tree(struct Translation_Data *translation_data)
{
	struct AST_Expression* ret;
	ret=wonky_malloc(sizeof(struct AST_Expression*));
	ret->type=OP_NOP;
	ret->value=get_expression_value_void(translation_data);
	return (struct AST*)ret;
}



struct AST_Type_Definition* get_type_definition_tree(struct Denoted_Type *definition)
{
	struct AST_Type_Definition *ret;
	ret=wonky_malloc(sizeof(struct AST_Type_Definition));
	ret->type=ST_TYPE_DEFINITION;
	ret->definition=definition;

	return ret;

}
struct AST_Object_Declaration* get_object_declaration_tree(struct Denoted_Object *object,struct Initialiser *initialiser)
{
	struct AST_Object_Declaration *ret;
	ret=wonky_malloc(sizeof(struct AST_Object_Declaration));
	ret->type=ST_OBJECT_DECLARATION;
	ret->object=object;
	ret->initializer=initialiser;
	return ret;
}

struct AST_Function_Definition* get_function_definition_tree(struct Scope *scope,struct Denoted_Function *function,struct AST_Compound_Statement *function_body,struct Translation_Data *translation_data)
{
	struct AST_Function_Definition *ret;
	ret=wonky_malloc(sizeof(struct AST_Function_Definition));
	ret->type=ST_FUNCTION_DEFINITION;
	ret->function=function;
	ret->body=function_body;

	if(!constraint_check_function_definition(ret,translation_data))
		return  (struct AST_Function_Definition*)get_error_tree((struct AST*)ret);
	else
		return ret;
}

struct AST_Function_Declaration* get_function_declaration_tree(struct Scope *scope,struct Denoted_Function *function)
{
	struct AST_Function_Declaration *ret;
	ret=wonky_malloc(sizeof(struct AST_Function_Declaration));
	ret->type=ST_FUNCTION_DECLARATION;
	ret->function=function;
	return ret;
}
struct AST_Translation_Unit* get_translation_unit_tree()
{
	struct AST_Translation_Unit *ret;
	ret=wonky_malloc(sizeof(struct AST_Translation_Unit));
	ret->type=TRANSLATION_UNIT;

	//ret->components=wonky_malloc(sizeof(struct Queue));
	
	ret->object_declarations=wonky_malloc(sizeof(struct Queue));
	ret->function_definitions=wonky_malloc(sizeof(struct Queue));

	ret->internal_linkage=get_linkage();
	ret->file_scope=get_normal_scope(NULL,FILE_SCOPE);

	Queue_Init(ret->object_declarations);
	Queue_Init(ret->function_definitions);

	return ret;
}

void delete_ast(struct AST* ast)
{
	switch(ast->type)
	{
		case OP_DESIGNATOR:
			delete_ast_designator_expression((struct AST_Designator*)ast);
			break;
		case OP_COMMA:
		case OP_ADDITION:
		case OP_SUBTRACTION:
		case OP_MUL:
		case OP_DIV:
		case OP_REMAINDER:
		case OP_ASSIGN:
		case OP_ADD_ASSIGN:
		case OP_SUBTRACT_ASSIGN:
		case OP_MULTIPLY_ASSIGN:
		case OP_REMAINDER_ASSIGN:
		case OP_DIV_ASSIGN:
		case OP_SHIFT_LEFT_ASSIGN:
		case OP_AND_ASSIGN:
		case OP_SHIFT_RIGHT_ASSIGN:
		case OP_XOR_ASSIGN:
		case OP_PIPE_ASSIGN:
		case OP_LOGICAL_AND:
		case OP_LOGICAL_OR:
		case OP_BITWISE_OR:
		case OP_BITWISE_AND:
		case OP_BITWISE_XOR:
		case OP_MEMBER_TROUGH_PTR:
		case OP_MEMBER:
		case OP_ARR_SUBSCRIPT:
		case OP_SHIFT_LEFT:
		case OP_LESS_EQ:
		case OP_NOT_EQUAL:
		case OP_EQUAL:
		case OP_GREATER:
		case OP_LESS:
		case OP_GREATER_EQ:
		case OP_SHIFT_RIGHT:
			delete_ast_binary_expression((struct AST_Binary_Expression*)ast);
			break;
		case OP_COND:
			delete_ast_conditional_expression((struct AST_Conditional_Expression*)ast);
			break;
		case OP_FUNCTION:
			delete_ast_function_expression((struct AST_Function_Expression*)ast);
			break;
		case OP_NOP:
			/*it is just a ast node*/
			wonky_free(ast);
			break;
		case OP_LOGICAL_NOT:
		case OP_BITWISE_NOT:
		case OP_ADDR_OF:
		case OP_DEREFERENCE:
		case OP_POSTFIX_INC:
		case OP_POSTFIX_DEC:
		case OP_PREFIX_INC:
		case OP_PREFIX_DEC:
		case OP_UNARY_PLUS:
		case OP_UNARY_MINUS:
		case OP_CAST:
		case OP_SIZEOF:
			delete_ast_unary_expression((struct AST_Unary_Expression*)ast);
			break;
		case OP_CONSTANT:
			delete_ast_constant((struct AST_Constant*)ast);
			break;
		case OP_STRING_LITERAL:
			delete_ast_string_literal((struct AST_String_Literal*)ast);
			break;
		case ST_COMPOUND:
			delete_ast_compound_statement((struct AST_Compound_Statement*)ast);
			break;
		case ST_SWITCH:
			delete_ast_switch_statement((struct AST_Switch_Statement*)ast);
			break;
		case ST_IF:
			delete_ast_if_statemtent((struct AST_If_Statement*)ast);
			break;
		case ST_WHILE:
			delete_ast_while_statemtent((struct AST_While_Statement*)ast);
			break;
		case ST_DO_WHILE:
			delete_ast_do_while_statement((struct AST_Do_While_Statement*)ast);
			break;
		case ST_GOTO:
			delete_ast_goto_statemtent((struct AST_Goto_Statement*)ast);
			break;
		case ST_LABEL:
			delete_ast_labeled_statement((struct AST_Labeled_Statement*)ast);
			break;
		case ST_CASE:
			delete_ast_case_statement((struct AST_Case_Statement*)ast);
			break;
		case ST_DEFAULT:
			delete_ast_default_statement((struct AST_Default_Statement*)ast);
			break;
		case ST_CONTINUE:
		case ST_BREAK:
			delete_ast_break_continue_statement((struct AST_Break_Continue_Statement*)ast);
			break;
		case ST_RETURN:
			delete_ast_return_statement((struct AST_Return_Statement*)ast);
			break;
		case ST_FOR:
			delete_ast_for_statement((struct AST_For_Statement*)ast);
			break;
		case ST_OBJECT_DECLARATION:
			delete_ast_object_declaration((struct AST_Object_Declaration*)ast);
			break;
		case ST_TYPE_DEFINITION:
			delete_ast_type_definition((struct AST_Type_Definition*)ast);
			break;
		case ST_FUNCTION_DEFINITION:
			delete_ast_function_definition((struct AST_Function_Definition*)ast);
			break;
		case ST_FUNCTION_DECLARATION:
			delete_ast_function_declaration((struct AST_Function_Declaration*)ast);
			break;
		case TRANSLATION_UNIT:
			delete_ast_translation_unit((struct AST_Translation_Unit*)ast);
			break;
		case ERROR:
			delete_ast_error((struct AST_Error*)ast);
			break;
		case ERROR_DECLARATION:
			delete_ast_declaration_error((struct AST_Declaration_Error*)ast);
			break;
		default:
			wonky_assert(SHOULD_NOT_REACH_HERE);
	}
}
void delete_ast_error(struct AST_Error *error)
{
	if(error->error!=NULL)
		delete_ast(error->error);
	wonky_free(error);
}
void delete_ast_declaration_error(struct AST_Declaration_Error *error)
{
	if(error->error!=NULL)
		delete_denoted_error((struct Denoted_Error*)error->error);
	wonky_free(error);
}
void delete_ast_binary_expression(struct AST_Binary_Expression *binary_expression)
{
	if(binary_expression->left!=NULL)
		delete_ast((struct AST*)binary_expression->left);
	if(binary_expression->right!=NULL)
		delete_ast((struct AST*)binary_expression->right);

	wonky_free(binary_expression);
}
void delete_ast_conditional_expression(struct AST_Conditional_Expression *cond_expression)
{
	
	if(cond_expression->left!=NULL)
		delete_ast((struct AST*)cond_expression->left);
	if(cond_expression->center!=NULL)
		delete_ast((struct AST*)cond_expression->center);
	if(cond_expression->right!=NULL)
		delete_ast((struct AST*)cond_expression->right);

	wonky_free(cond_expression);
}
void delete_ast_function_expression(struct AST_Function_Expression *function_expression)
{
	struct Queue_Node *it;
	size_t i;

	if(function_expression->id!=NULL)
		delete_ast((struct AST*)function_expression->id);
	if(function_expression->number_of_arguments!=0)
	{
		for(i=0;i<function_expression->number_of_arguments;++i)
		{
			delete_ast((struct AST*)function_expression->arg_list[i]);
		}
		wonky_free(function_expression->arg_list);
	}

	wonky_free(function_expression);
	
}
void delete_ast_designator_expression(struct AST_Designator *designator)
{
	wonky_free(designator);
}
void delete_ast_unary_expression(struct AST_Unary_Expression *unary_expression)
{
	if(unary_expression->operand!=NULL)
		delete_ast((struct AST*)unary_expression->operand);
	wonky_free(unary_expression);
}
void delete_ast_labeled_statement(struct AST_Labeled_Statement *labeled_statement)
{
	if(labeled_statement->label!=NULL)
		delete_denoted((struct Denoted*)labeled_statement->label);	
	wonky_free(labeled_statement);
}
void delete_ast_default_statement(struct AST_Default_Statement *default_statement)
{
	wonky_free(default_statement);
}
void delete_ast_break_continue_statement(struct AST_Break_Continue_Statement *break_continue)
{
	wonky_free(break_continue);
}
void delete_ast_compound_statement(struct AST_Compound_Statement *compound_statement)
{
	if(compound_statement->scope!=NULL)
		delete_scope(compound_statement->scope);
	while(compound_statement->components->size>0)
		delete_ast((struct AST*)Queue_Pop(compound_statement->components));
	wonky_free(compound_statement);
}
void delete_ast_for_statement(struct AST_For_Statement *for_statement)
{
	if(for_statement->condition!=NULL)
		delete_ast(for_statement->condition);
	if(for_statement->initialisation!=NULL)
		delete_ast(for_statement->initialisation);
	if(for_statement->update!=NULL)
		delete_ast(for_statement->update);
	if(for_statement->body_statement!=NULL)
		delete_ast(for_statement->body_statement);
	wonky_free(for_statement);
}
void delete_ast_while_statemtent(struct AST_While_Statement *while_statement)
{
	if(while_statement->condition!=NULL)
		delete_ast(while_statement->condition);
	if(while_statement->body_statement!=NULL)
		delete_ast(while_statement->body_statement);
	wonky_free(while_statement);
}
void delete_ast_do_while_statement(struct AST_Do_While_Statement *do_while_statement)
{
	if(do_while_statement->condition!=NULL)
		delete_ast(do_while_statement->condition);
	if(do_while_statement->body_statement!=NULL)
		delete_ast(do_while_statement->body_statement);
	wonky_free(do_while_statement);
}
void delete_ast_if_statemtent(struct AST_If_Statement *if_statement)
{
	if(if_statement->condition!=NULL)
		delete_ast(if_statement->condition);
	if(if_statement->body_statement!=NULL)
		delete_ast(if_statement->body_statement);
	if(if_statement->else_statement!=NULL)
		delete_ast(if_statement->else_statement);
	wonky_free(if_statement);
}
void delete_ast_goto_statemtent(struct AST_Goto_Statement *goto_statement)
{
	wonky_free(goto_statement);
}
void delete_ast_switch_statement(struct AST_Switch_Statement *switch_statement)
{
	if(switch_statement->condition!=NULL)
		delete_ast((struct AST*)switch_statement->condition);
	if(switch_statement->body_statement!=NULL)
		delete_ast(switch_statement->body_statement);

	while(switch_statement->cases->size>0)
		Queue_Pop(switch_statement->cases);

	wonky_free(switch_statement->cases);
	wonky_free(switch_statement);
}
void delete_ast_case_statement(struct AST_Case_Statement *case_statement)
{
	if(case_statement->control)
		delete_ast((struct AST*)case_statement->control);	
	if(case_statement->statement)
		delete_ast(case_statement->statement);	
	wonky_free(case_statement);
}
void delete_ast_return_statement(struct AST_Return_Statement *return_statement)
{
	if(return_statement->return_expression!=NULL)
		delete_ast(return_statement->return_expression);
	wonky_free(return_statement);
}
void delete_ast_type_definition(struct AST_Type_Definition *type_definition)
{
	/*deleting denoted objects in scopes*/
	wonky_free(type_definition);
}
void delete_ast_object_declaration(struct AST_Object_Declaration *object_declaration)
{
	wonky_free(object_declaration);

}
void delete_ast_function_definition(struct AST_Function_Definition *function_definition)
{
	wonky_free(function_definition);
}
void delete_ast_function_declaration(struct AST_Function_Declaration *function_declaration)
{
	wonky_free(function_declaration);
}
void delete_ast_translation_unit(struct AST_Translation_Unit *translation_unit)
{
	while(translation_unit->function_definitions->size>0)
		delete_ast((struct AST*)Queue_Pop(translation_unit->function_definitions));
	while(translation_unit->object_declarations->size>0)
		delete_ast((struct AST*)Queue_Pop(translation_unit->object_declarations));
	if(translation_unit->file_scope!=NULL)
		delete_scope(translation_unit->file_scope);
	delete_linkage(translation_unit->internal_linkage);
	wonky_free(translation_unit);
}
void delete_ast_constant(struct AST_Constant *constant)
{
	if(constant->value!=NULL)
		wonky_free(constant->value);
	wonky_free(constant);
}


void delete_ast_string_literal(struct AST_String_Literal *string)
{
	wonky_free(string);
}



#endif