#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