WONKY



LOG | FILES | OVERVIEW


F diff --git a/src/backend/print/print.c b/src/backend/print/print.c --- a/src/backend/print/print.c +++ b/src/backend/print/print.c
}
void print_function_expression_tree(FILE *out,struct AST_Function_Expression *function_call)
{
- struct Queue_Node *it;
+ size_t i;
print_ast(out,(struct AST*)function_call->id);
fprintf(out,"(");
- if(function_call->arguments.size>0)
+ if(function_call->number_of_arguments>0)
{
- fprintf(out,"\n");
- for(it=function_call->arguments.first;it!=function_call->arguments.last;it=it->prev)
+ for(i=0;i<function_call->number_of_arguments;++i)
{
- print_ast(out,(struct AST*)(struct AST*)(it->data));
- fprintf(out,",\n");
+ print_ast(out,(struct AST*)function_call->arg_list[i]);
+ if(i!=function_call->number_of_arguments-1)
+ fprintf(out,",");
}
- if(it!=NULL)
- {
- print_ast(out,(struct AST*)(struct AST*)(it->data));
- }
-
}
fprintf(out,")");
}
F diff --git a/src/frontend/lex/lexer.c b/src/frontend/lex/lexer.c --- a/src/frontend/lex/lexer.c +++ b/src/frontend/lex/lexer.c
return ((struct token*)(translation_data->tokens->first->data))->type;
}
+ char compare_tokens(struct token *a,struct token *b)
+ {
+ size_t i;
+ if(a->data_size!=b->data_size)
+ return 0;
+ for(i=0;i<a->data_size;++i)
+ {
+ if(a->data[i]!=b->data[i])
+ return 0;
+ }
+ return 1;
+ }
struct token* get_next_token(struct Source_File *src,struct automata_entry *start_state,char skip_new_line)
{
F diff --git a/src/frontend/lex/lexer.h b/src/frontend/lex/lexer.h --- a/src/frontend/lex/lexer.h +++ b/src/frontend/lex/lexer.h
char get_and_check_unsafe(struct Translation_Data *translation_data,enum KEYWORDS kw);
void chomp(struct Translation_Data *translation_data);
enum KEYWORDS kw_get(struct Translation_Data *translation_data);
+ char compare_tokens(struct token *a,struct token *b);
char src_getc(struct Source_File *src,char skip_line_splice,char skip_comments,char skip_new_line);
void src_ungetc(struct Source_File *src);
F diff --git a/src/frontend/parse/parse_declaration.c b/src/frontend/parse/parse_declaration.c --- a/src/frontend/parse/parse_declaration.c +++ b/src/frontend/parse/parse_declaration.c
/*check if this is a function definition*/
if(parse_function_definitions && get_and_check(translation_data,KW_OPEN_CURLY))
{
+ struct Type_Function *function_type;
+ function_type=(struct Type_Function*)((struct Denoted_Function*)hold)->type;
((struct Denoted_Function*)hold) ->body=
- (struct AST_Compound_Statement*)parse_finish_compound_statement(translation_data,scope);
+ (struct AST_Compound_Statement*)parse_finish_compound_statement(translation_data,(struct Scope*)function_type->function_prototype_scope);
Queue_Push(where_to_push,get_function_definition_tree(scope,(struct Denoted_Function*)hold));
Scope_Push(scope,hold,translation_data);
break;
F diff --git a/src/frontend/parse/parse_expression.c b/src/frontend/parse/parse_expression.c --- a/src/frontend/parse/parse_expression.c +++ b/src/frontend/parse/parse_expression.c
struct AST_Function_Expression* parse_arglist(struct Translation_Data *translation_data,struct Scope *scope,struct AST_Expression* id)
{
struct AST_Function_Expression *ret;
+ struct AST_Expression *hold_expression;
+ struct Queue arg_list;
+
+ Queue_Init(&arg_list);
- ret=get_function_expression_tree(id,scope);
- ret->id=id;
if(get_and_check(translation_data,KW_CLOSE_NORMAL))
{
- return ret;
+ return get_function_expression_tree(id,&arg_list,translation_data);
}
+
do
{
- Queue_Push(&ret->arguments,parse_assignment_expression(translation_data,scope));
- } while(get_and_check(translation_data,KW_COMMA));
+ hold_expression=parse_assignment_expression(translation_data,scope);
+ if(hold_expression==NULL)
+ {
+ while(arg_list.size>0)
+ delete_ast((struct AST*)Queue_Pop(&arg_list));
+ push_translation_error("error in argument list in function call expression",translation_data);
+ return NULL;
+ }
+ Queue_Push(&arg_list,hold_expression);
+ }while(get_and_check(translation_data,KW_COMMA));
+
+ ret=get_function_expression_tree(id,&arg_list,translation_data);
+ assert(arg_list.size==0);
+
if(get_and_check(translation_data,KW_CLOSE_NORMAL))
{
return ret;
}else
{
push_translation_error("expected ')' here",translation_data);
- return (struct AST_Function_Expression*)get_error_tree((struct AST*)ret);
+ delete_ast((struct AST*)ret);
+ return NULL;
}
}
F diff --git a/src/semantics/ast.c b/src/semantics/ast.c --- a/src/semantics/ast.c +++ b/src/semantics/ast.c
return ret;
}
- struct AST_Function_Expression* get_function_expression_tree(struct AST_Expression *id,struct Scope *scope)
+ 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;
+
+ id_type=(struct Type_Function*)extract_expresion_value_type(id->value,translation_data);
ret=malloc(sizeof(struct AST_Function_Expression));
ret->type=OP_FUNCTION;
+ ret->value=get_expression_value_rvalue(get_temp_object(id_type->return_type));
ret->id=id;
- Queue_Init(&ret->arguments);
- return ret;
+ ret->number_of_arguments=arg_list->size;
+
+ ret->arg_list=calloc(ret->number_of_arguments,sizeof(struct AST_Expression*));
+ for(i=0;i<ret->number_of_arguments;++i)
+ {
+ assert(arg_list->size>0);
+ ret->arg_list[i]=(struct AST_Expression*)Queue_Pop(arg_list);
+ }
+ assert(arg_list->size==0);
+ if(constraint_check_function_expression(ret,translation_data))
+ {
+ return ret;
+ }
+ else
+ {
+ delete_ast((struct AST*)ret);
+ push_translation_error("constraint check violation in function call expression",translation_data);
+ return NULL;
+ }
}
struct AST_Unary_Expression* get_unary_expression_tree(struct AST_Expression *operand,struct Expression_Value *value,enum AST_Type type)
{
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);
- while(function_expression->arguments.size>0)
- delete_ast(Queue_Pop(&function_expression->arguments));
+ 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]);
+ }
+ free(function_expression->arg_list);
+ }
free(function_expression);
F diff --git a/src/semantics/ast.h b/src/semantics/ast.h --- a/src/semantics/ast.h +++ b/src/semantics/ast.h
struct Expression_Value *value;
struct AST_Expression *id;
- /*queue of astrees*/
- struct Queue arguments;
+
+ size_t number_of_arguments;
+ struct AST_Expression **arg_list;
};
struct AST_Constant
struct AST_Binary_Expression* get_struct_union_member_trough_ptr_tree(struct AST_Expression *left,struct token *id,struct Translation_Data *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_Function_Expression* get_function_expression_tree(struct AST_Expression *id,struct Scope *scope);
+ struct AST_Function_Expression* get_function_expression_tree(struct AST_Expression *id,struct Queue *arg_list,struct Translation_Data *translation_data);
struct AST_Unary_Expression* get_unary_expression_tree(struct AST_Expression *operand,struct Expression_Value *value,enum AST_Type type);
struct AST_Unary_Expression* get_indirection_expression_tree(struct AST_Expression *operand,struct Translation_Data *translation_data);
F diff --git a/src/semantics/identifiers/denoted.c b/src/semantics/identifiers/denoted.c --- a/src/semantics/identifiers/denoted.c +++ b/src/semantics/identifiers/denoted.c
{
if( AS_DENOTED_OBJECT_PTR(denoted)->linkage!=LINKAGE_NONE )
return;
+ }else if( ((struct Denoted*)denoted)->denotation == DT_Function )
+ {
+ if( AS_DENOTED_FUNCTION(denoted)->linkage!=LINKAGE_NONE )
+ return;
}
delete_denoted(denoted);
}
F diff --git a/src/semantics/value/constraints.c b/src/semantics/value/constraints.c --- a/src/semantics/value/constraints.c +++ b/src/semantics/value/constraints.c
}
}
}
- char constraint_check_function_expression(struct AST_Expression *id,struct Scope *scope,struct Translation_Data *translation_data)
+ char constraint_check_function_expression(struct AST_Function_Expression *proposed_function,struct Translation_Data *translation_data)
{
+ struct Type *expected_argument_type;
+ struct Type *given_argument_type;
+ struct Type_Function *proposed_function_type;
+ size_t i;
+
+ proposed_function_type=(struct Type_Function*)extract_expresion_value_type(proposed_function->id->value,translation_data);
+ if(proposed_function_type->specifier!=TS_FUNC)
+ {
+ push_translation_error("is not a function",translation_data);
+ return 0;
+ }
+
+ if(proposed_function_type->number_of_arguments!=proposed_function->number_of_arguments)
+ {
+ push_translation_error("mismatching number of arguments",translation_data);
+ return 0;
+ }
+
+ for(i=0;i<proposed_function->number_of_arguments;++i)
+ {
+ expected_argument_type=proposed_function_type->arguments[i]->object->type;
+ given_argument_type=extract_expresion_value_type(proposed_function->arg_list[i]->value,translation_data);
+ if(!types_are_compatible_unqualified(expected_argument_type,given_argument_type))
+ {
+ push_translation_error("incompatible types of argument",translation_data);
+ return 0;
+ }
+ }
return 1;
}
char constraint_check_indirection_expression(struct AST_Expression *operand,struct Translation_Data *translation_data)
F diff --git a/src/semantics/value/constraints.h b/src/semantics/value/constraints.h --- a/src/semantics/value/constraints.h +++ b/src/semantics/value/constraints.h
char constraint_check_struct_union_member_expression(struct AST_Expression *left,struct token *id,struct Translation_Data *translation_data);
char constraint_check_struct_union_member_trough_ptr_expression(struct AST_Expression *left,struct token *id,struct Translation_Data *translation_data);
char constraint_check_conditional_expression(struct AST_Expression *left,struct AST_Expression *center,struct AST_Expression *right,struct Translation_Data *translation_data);
- char constraint_check_function_expression(struct AST_Expression *id,struct Scope *scope,struct Translation_Data *translation_data);
+ char constraint_check_function_expression(struct AST_Function_Expression *proposed_function,struct Translation_Data *translation_data);
char constraint_check_indirection_expression(struct AST_Expression *operand,struct Translation_Data *translation_data);
char constraint_check_address_expression(struct AST_Expression *operand,struct Translation_Data *translation_data);
char constraint_check_sizeof_by_type(struct Type *type);
F diff --git a/src/semantics/value/type.c b/src/semantics/value/type.c --- a/src/semantics/value/type.c +++ b/src/semantics/value/type.c
return a==b;
}
-
+ /* 6.2.7
+ * two types have compatible type if their types are the same.
+ * Additional
+ *
+ * */
char types_are_compatible(struct Type *a,struct Type *b)
{
- return 1;
+ return types_are_identical(a,b) || ( type_is_constant(a)==type_is_constant(b) && type_is_volatile(a)==type_is_volatile(b)
+ && types_are_compatible_inner(a,b) );
}
char types_are_compatible_unqualified(struct Type *a,struct Type *b)
{
+ return types_are_identical(a,b) || types_are_compatible_inner(a,b);
+ }
+ char types_are_compatible_inner(struct Type *a,struct Type *b)
+ {
+ switch(a->specifier)
+ {
+ case TS_STRUCT:
+ case TS_UNION:
+ if(b->specifier!=a->specifier)
+ return 0;
+ else
+ return types_of_struct_unions_are_compatible_unqualified(
+ ((struct Type_Struct_Union*)a)->struct_union,
+ ((struct Type_Struct_Union*)b)->struct_union);
+ case TS_POINTER:
+ if(b->specifier!=TS_POINTER)
+ return 0;
+ else
+ return types_of_pointers_are_compatible_unqualified((struct Type_Pointer*)a,(struct Type_Pointer*)b);
+ case TS_ARRAY:
+ if(b->specifier!=TS_ARRAY)
+ return 0;
+ else
+ return types_of_arrays_are_compatible_unqualified((struct Type_Array*)a,(struct Type_Array*)b);
+ case TS_BITFIELD:
+ if(b->specifier!=TS_BITFIELD)
+ return 0;
+ else
+ return types_of_bitfields_are_compatible_unqalified((struct Type_Bit_Field*)a,(struct Type_Bit_Field*)b);
+ case TS_FUNC:
+ if(b->specifier!=TS_FUNC)
+ return 0;
+ else
+ return types_of_functions_are_compatible_unqualified((struct Type_Function*)a,(struct Type_Function*)b);
+ case TS_VOID:
+ case TS_CHAR:
+ case TS_INT:
+ case TS_FLOAT:
+ case TS_DOUBLE:
+ if(b->specifier!=a->specifier)
+ {
+ return 0;
+ }
+ else
+ {
+ struct Type_Basic *basic_a;
+ struct Type_Basic *basic_b;
+
+ basic_a=(struct Type_Basic*)a;
+ basic_b=(struct Type_Basic*)b;
+
+ if(basic_a->constraint!=basic_b->constraint)
+ return 0;
+ if(basic_a->sign!=basic_b->sign)
+ return 0;
+
+ return 1;
+ }
+ }
+ assert(0);
+ return 0;
+ }
+ char types_of_pointers_are_compatible_unqualified(struct Type_Pointer *a,struct Type_Pointer *b)
+ {
+ return types_are_compatible(a->points_to,b->points_to);
+ }
+ char types_of_arrays_are_compatible_unqualified(struct Type_Array *a,struct Type_Array *b)
+ {
+ if(!types_are_compatible(a->is_array_of,b->is_array_of))
+ return 0;
+ /*0 number of elements means incomplete array type*/
+ if(a->number_of_elements==0 || b->number_of_elements==0)
+ return 1;
+ return a->number_of_elements==b->number_of_elements;
+ }
+ char types_of_functions_are_compatible_unqualified(struct Type_Function *a,struct Type_Function *b)
+ {
+ size_t current_argument;
+
+ if(!types_are_compatible(a->return_type,b->return_type))
+ return 0;
+ /*TODO add check for variadic function*/
+ if(a->number_of_arguments!=b->number_of_arguments)
+ return 0;
+
+ for(current_argument=0;current_argument<a->number_of_arguments;++current_argument)
+ {
+ if(!types_are_compatible(a->arguments[current_argument]->object->type,b->arguments[current_argument]->object->type))
+ return 0;
+ }
+ return 1;
+ }
+ char types_of_struct_unions_are_compatible_unqualified(struct Struct_Union *a,struct Struct_Union *b)
+ {
+ struct Queue_Node *it_a;
+ struct Queue_Node *it_b;
+
+ if( (a->id==NULL || b->id==NULL ) && b->id!=a->id)
+ return 0;
+ if(a->id!=NULL && !compare_tokens(a->id,b->id))
+ return 0;
+ if(a->members->size!=b->members->size)
+ return 0;
+ for(it_a=a->members->first,it_b=a->members->first;it_a!=NULL && it_b!=NULL; it_a=it_a->prev,it_b=it_b->prev)
+ {
+ struct Denoted_Object *object_a;
+ struct Denoted_Object *object_b;
+
+ object_a=(struct Denoted_Object*)it_a->data;
+ object_b=(struct Denoted_Object*)it_b->data;
+
+ if(!types_are_compatible( object_a->object->type, object_b->object->type))
+ return 0;
+ if((object_a->id==NULL || object_b->id==NULL) && object_b->id!=object_a->id)
+ return 0;
+ if(object_a->id!=NULL && !compare_tokens(object_a->id,object_b->id))
+ return 0;
+ }
+ return 1;
+ }
+ char types_of_bitfields_are_compatible_unqalified(struct Type_Bit_Field *a,struct Type_Bit_Field *b)
+ {
return 1;
}
+ char types_of_enum_are_compatible_unqualified(struct Type_Enum *a,struct Type_Enum *b)
+ {
+ return 1;
+ }
+
char type_is_scalar(struct Type *type)
{
return (type->specifier==TS_POINTER && type_is_basic(AS_TYPE_PTR_PTR(type)->points_to) && AS_BASIC_TYPE_PTR(AS_TYPE_PTR_PTR(type)->points_to)->specifier==TS_VOID);
}
+ char type_is_constant(struct Type *type)
+ {
+ switch(type->specifier)
+ {
+ case TS_VOID:
+ case TS_CHAR:
+ case TS_INT:
+ case TS_FLOAT:
+ case TS_DOUBLE:
+ return ((struct Type_Basic*)type)->is_const;
+ case TS_STRUCT:
+ case TS_UNION:
+ return ((struct Type_Struct_Union*)type)->is_const ||
+ ((struct Type_Struct_Union*)type)->struct_union->has_constant_member;
+ case TS_ENUM:
+ return ((struct Type_Enum*)type)->is_const;
+ case TS_POINTER:
+ return ((struct Type_Pointer*)type)->is_const;
+ case TS_BITFIELD:
+ return type_is_constant(((struct Type_Bit_Field*)type)->base);
+ }
+ return 0;
+ }
+ char type_is_volatile(struct Type *type)
+ {
+ switch(type->specifier)
+ {
+ case TS_VOID:
+ case TS_CHAR:
+ case TS_INT:
+ case TS_FLOAT:
+ case TS_DOUBLE:
+ return ((struct Type_Basic*)type)->is_volatile;
+ case TS_STRUCT:
+ case TS_UNION:
+ /*
+ return ((struct Type_Struct_Union*)type)->is_const ||
+ ((struct Type_Struct_Union*)type)->struct_union->has_volatile_member;
+ */
+ return ((struct Type_Struct_Union*)type)->is_volatile;
+ case TS_ENUM:
+ return ((struct Type_Enum*)type)->is_const;
+ case TS_POINTER:
+ return ((struct Type_Pointer*)type)->is_const;
+ case TS_BITFIELD:
+ return type_is_volatile(((struct Type_Bit_Field*)type)->base);
+ }
+ return 0;
+ }
#endif
F diff --git a/src/semantics/value/type.h b/src/semantics/value/type.h --- a/src/semantics/value/type.h +++ b/src/semantics/value/type.h
char types_are_identical(struct Type *a,struct Type *b);
char types_are_compatible(struct Type *a,struct Type *b);
char types_are_compatible_unqualified(struct Type *a,struct Type *b);
+ char types_are_compatible_inner(struct Type *a,struct Type *b);
+ char types_of_pointers_are_compatible_unqualified(struct Type_Pointer *a,struct Type_Pointer *b);
+ char types_of_arrays_are_compatible_unqualified(struct Type_Array *a,struct Type_Array *b);
+ char types_of_functions_are_compatible_unqualified(struct Type_Function *a,struct Type_Function *b);
+ char types_of_struct_unions_are_compatible_unqualified(struct Struct_Union *a,struct Struct_Union *b);
+ char types_of_bitfields_are_compatible_unqalified(struct Type_Bit_Field *a,struct Type_Bit_Field *b);
+ char types_of_enum_are_compatible_unqualified(struct Type_Enum *a,struct Type_Enum *b);
char type_is_of_object(struct Type *type);
char type_is_complete(struct Type *type);
char type_is_pointer_to_incomplete_type(struct Type *type);
char type_is_pointer_to_void(struct Type *type);
+ /*these return 0 if constant/volatile-ness make no sense for the type*/
+ char type_is_constant(struct Type *type);
+ char type_is_volatile(struct Type *type);
+
int type_get_integer_conversion_rank(struct Type_Basic *type);