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
if(lab->type!=ST_LABEL)
print_ast_enum(out,lab->type);
if(lab->label!=NULL)
- print_token(out,lab->label);
- fprintf(out,":\n");
- print_ast(out,(struct AST*)lab->statement);
+ print_denoted(out,(struct Denoted*)lab->label);
}
void print_compound_statement_tree(FILE *out,struct AST_Compound_Statement *comp)
{
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
hold_function->body=
(struct AST_Compound_Statement*)parse_finish_compound_statement(translation_data,(struct Scope*)function_type->function_prototype_scope,NULL,NULL);
- Queue_Push(where_to_push,get_function_definition_tree(scope,(struct Denoted_Function*)hold));
+ Queue_Push(where_to_push,get_function_definition_tree(scope,(struct Denoted_Function*)hold,translation_data));
break;
}
/*this is a function declaration*/
F diff --git a/src/frontend/parse/parse_statement.c b/src/frontend/parse/parse_statement.c
--- a/src/frontend/parse/parse_statement.c
+++ b/src/frontend/parse/parse_statement.c
case KW_ID:
if(check(translation_data,KW_COLUMN,1))
{
- return parse_finish_labeled_statement(translation_data,scope,ST_LABEL,upper_loop,upper_switch);
+ return parse_finish_labeled_statement(translation_data,scope,upper_loop,upper_switch);
}else
{
return parse_expression_statement(translation_data,scope,upper_loop,upper_switch);
if(check(translation_data,KW_ID,0))
{
- ret=(struct AST*)get_goto_statement_tree(Queue_Pop(translation_data->tokens),scope);
+ ret=(struct AST*)get_goto_statement_tree(Queue_Pop(translation_data->tokens),scope,translation_data);
if(get_and_check(translation_data,KW_SEMI_COLUMN))
{
return ret;
else
{
push_translation_error(" label expected in goto statement",translation_data);
- return (struct AST*)get_error_tree((struct AST*)get_goto_statement_tree(NULL,NULL));
+ return (struct AST*)get_error_tree(NULL);
}
}
id:
statement
*/
- struct AST* parse_finish_labeled_statement(struct Translation_Data* translation_data,struct Scope *scope,enum AST_Type type,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch)
+ struct AST* parse_finish_labeled_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch)
{
- struct AST_Labeled_Statement *ret;
- if(check(translation_data,KW_ID,0))
- {
- ret=get_labeled_statement_tree(Queue_Pop(translation_data->tokens),NULL,type,translation_data,scope);
- if(get_and_check(translation_data,KW_COLUMN))
- {
- ret->statement=parse_statement(translation_data,scope,upper_loop,upper_switch);
- return (struct AST*)ret;
- }else
- {
- push_translation_error(" ':' expected in labeled statement",translation_data);
- return (struct AST*)get_error_tree((struct AST*)ret);
- }
- }else
- {
- push_translation_error(" label expected in labeled statement",translation_data);
- return (struct AST*)get_error_tree(NULL);
- }
+ struct AST *hold_statement;
+ struct token *hold_id;
+ /*id and ':' are checked for in the parse_statement function*/
+
+ hold_id=Queue_Pop(translation_data->tokens);
+ chomp(translation_data); /* ':' */
+ hold_statement=parse_statement(translation_data,scope,upper_loop,upper_switch);
+
+ return (struct AST*)get_labeled_statement_tree(hold_id,hold_statement,ST_LABEL,translation_data,scope);
}
/*
*/
struct AST* parse_finish_default_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch)
{
- struct AST_Labeled_Statement *ret;
- ret=get_labeled_statement_tree(NULL,NULL,ST_DEFAULT,translation_data,scope);
+ struct AST *statement;
if(get_and_check(translation_data,KW_COLUMN))
{
- ret->statement=parse_statement(translation_data,scope,upper_loop,upper_switch);
- return (struct AST*)ret;
+ statement=parse_statement(translation_data,scope,upper_loop,upper_switch);
+ return (struct AST*)get_default_statement_tree(statement,translation_data);
}else
{
push_translation_error(" ':' expected in default statement",translation_data);
- return (struct AST*)get_error_tree((struct AST*)ret);
+ return (struct AST*)get_error_tree((struct AST*)NULL);
}
}
/*
F diff --git a/src/frontend/parse/parse_statement.h b/src/frontend/parse/parse_statement.h
--- a/src/frontend/parse/parse_statement.h
+++ b/src/frontend/parse/parse_statement.h
struct AST* parse_finish_break_statement(struct Translation_Data* translation_data,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
struct AST* parse_finish_return_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
struct AST* parse_expression_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
- struct AST* parse_finish_labeled_statement(struct Translation_Data* translation_data,struct Scope *scope,enum AST_Type type,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
+ struct AST* parse_finish_labeled_statement(struct Translation_Data* translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
struct AST* parse_finish_case_statement(struct Translation_Data *translation_data,struct Scope *scope,struct AST *upper_loop,struct AST_Switch_Statement *upper_switch);
F diff --git a/src/program/gcc_error.c b/src/program/gcc_error.c
--- a/src/program/gcc_error.c
+++ b/src/program/gcc_error.c
char *ret;
size_t filename_length;
- filename_length=gstrlen(filename);
+ if(filename!=NULL)
+ filename_length=gstrlen(filename);
+ else
+ filename_length=sizeof("NULL")+100;
+
ret=calloc(filename_length+64,1);
sprintf(ret,"%s %zu:%zu ",filename,line,column);
F diff --git a/src/semantics/ast.c b/src/semantics/ast.c
--- a/src/semantics/ast.c
+++ b/src/semantics/ast.c
struct AST_Labeled_Statement *ret;
ret=malloc(sizeof(struct AST_Labeled_Statement));
ret->type=type;
- ret->label=label;
+
+ 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=malloc(sizeof(struct AST_Default_Statement));
+ ret->type=ST_DEFAULT;
ret->statement=statement;
return ret;
}
}
- struct AST_Goto_Statement* get_goto_statement_tree(struct token *label,struct Scope *scope)
+ struct AST_Goto_Statement* get_goto_statement_tree(struct token *label,struct Scope *scope,struct Translation_Data *translation_data)
{
struct AST_Goto_Statement *ret;
struct Denoted_Statement *hold_statement;
hold_statement=check_label(scope,label);
if(hold_statement==NULL)
{
- hold_statement=(struct Denoted_Statement*)get_denoted_statement(label,NULL,NULL);
+ push_label(scope,label,NULL,translation_data);
+ hold_statement=check_label(scope,label);
}
ret->label=hold_statement;
return ret;
}
- struct AST_Function_Definition* get_function_definition_tree(struct Scope *scope,struct Denoted_Function *function)
+ struct AST_Function_Definition* get_function_definition_tree(struct Scope *scope,struct Denoted_Function *function,struct Translation_Data *translation_data)
{
struct AST_Function_Definition *ret;
ret=malloc(sizeof(struct AST_Function_Definition));
ret->type=ST_FUNCTION_DEFINITION;
ret->function=function;
- return ret;
+
+ 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)
void delete_ast_labeled_statement(struct AST_Labeled_Statement *labeled_statement)
{
if(labeled_statement->label!=NULL)
- free(labeled_statement->label);
- if(labeled_statement->statement!=NULL)
- delete_ast(labeled_statement->statement);
+ delete_denoted((struct Denoted*)labeled_statement->label);
free(labeled_statement);
}
void delete_ast_compound_statement(struct AST_Compound_Statement *compound_statement)
F diff --git a/src/semantics/ast.h b/src/semantics/ast.h
--- a/src/semantics/ast.h
+++ b/src/semantics/ast.h
struct AST_Labeled_Statement
{
enum AST_Type type;
- struct token *label;
- struct AST *statement;
+ struct Denoted_Statement *label;
};
struct AST_Case_Statement
{
struct AST_Expression *expression;
struct AST *statement;
};
+ struct AST_Default_Statement
+ {
+ enum AST_Type type;
+ struct AST *statement;
+ };
struct AST_Compound_Statement
{
enum AST_Type type;
- struct AST_Labeled_Statement* get_labeled_statement_tree(struct token *label,struct AST* statement,enum AST_Type type,struct Translation_Data *translation_data,struct Scope *scope);
+ struct AST_Labeled_Statement* get_labeled_statement_tree(struct token *label,struct AST *statement,enum AST_Type type,struct Translation_Data *translation_data,struct Scope *scope);
+ struct AST_Default_Statement* get_default_statement_tree(struct AST *statement,struct Translation_Data *translation_data);
struct AST_Compound_Statement* get_compound_statement_tree(struct Scope *parent_scope);
struct AST_If_Statement* get_if_statement_tree();
struct AST_Switch_Statement* get_switch_statement_tree();
struct AST_Do_While_Statement* get_do_while_statement_tree();
struct AST_For_Statement* get_for_statement_tree();
struct AST_Return_Statement* get_return_statement_tree(struct AST* return_expression,struct Translation_Data *translation_data,struct Scope *scope);
- struct AST_Goto_Statement* get_goto_statement_tree(struct token *label,struct Scope *scope);
+ struct AST_Goto_Statement* get_goto_statement_tree(struct token *label,struct Scope *scope,struct Translation_Data *translation_data);
struct AST* get_nop_tree();
struct AST_Type_Definition* get_type_definition_tree(struct Denoted_Type *definition);
struct AST_Object_Declaration* get_object_declaration_tree(struct Denoted_Object *object);
struct AST_Function_Declaration* get_function_declaration_tree(struct Scope *scope,struct Denoted_Function *function);
- struct AST_Function_Definition* get_function_definition_tree(struct Scope *scope,struct Denoted_Function *function);
+ struct AST_Function_Definition* get_function_definition_tree(struct Scope *scope,struct Denoted_Function *function,struct Translation_Data *translation_data);
struct AST_Translation_Unit* get_translation_unit_tree();
F diff --git a/src/semantics/constraints/statement_constraints.c b/src/semantics/constraints/statement_constraints.c
--- a/src/semantics/constraints/statement_constraints.c
+++ b/src/semantics/constraints/statement_constraints.c
#define WONKY_STATEMENT_CONSTRAINTS_C WONKY_STATEMENT_CONSTRAINTS_C
#include <statement_constraints.h>
+ _Bool constraint_check_labeled_statement(struct AST_Labeled_Statement *label,struct Translation_Data *translation_data)
+ {
+ return 1;
+ }
_Bool constraint_check_return_statement(struct AST *return_expression,struct Type *return_type,struct Translation_Data *translation_data)
{
assert(0);
}
+ _Bool constraint_check_function_definition(struct AST_Function_Definition *function,struct Translation_Data *translation_data)
+ {
+ struct Function_Scope *function_scope;
+ struct Queue_Node *it;
+
+ function_scope=function->function->function_scope;
+
+ for(it=function_scope->label_order->first;it!=NULL;it=it->prev)
+ {
+ if(!denoted_statement_is_declared((struct Denoted_Statement*)it->data))
+ {
+ push_translation_error("Label %t is used but not declared",translation_data,
+ ((struct Denoted_Statement*)it->data)->label
+ );
+ return 0;
+ }
+ if(!constraint_check_labeled_statement(((struct AST_Labeled_Statement*)it->data),translation_data))
+ return 0;
+ }
+
+ return 1;
+ }
#endif
F diff --git a/src/semantics/constraints/statement_constraints.h b/src/semantics/constraints/statement_constraints.h
--- a/src/semantics/constraints/statement_constraints.h
+++ b/src/semantics/constraints/statement_constraints.h
/*_Bool constraint_check_case_statement(struct ,struct Translation_Data *translation_data);*/
/*_Bool constraint_check_default(struct ,struct Translation_Data *translation_data);*/
- _Bool constraint_check_label(struct AST_Labeled_Statement *label,struct AST_Compound_Statement *function_block,struct Translation_Data *translation_data);
+ _Bool constraint_check_labeled_statement(struct AST_Labeled_Statement *label,struct Translation_Data *translation_data);
/*must have scallar controlling expression*/
_Bool constraint_check_if_statement(struct AST_If_Statement *if_statement,struct Translation_Data *translation_data);
/*must be in a function and must return with the function return type , empty expressions are premmited under functions returning void*/
_Bool constraint_check_return_statement(struct AST *return_expression,struct Type *return_type,struct Translation_Data *translation_data);
+ _Bool constraint_check_compound_statement(struct AST_Compound_Statement *block,struct Translation_Data *translation_data);
+
+ /*Not really a statement*/
+ _Bool constraint_check_function_definition(struct AST_Function_Definition *function,struct Translation_Data *translation_data);
#endif
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
+ _Bool denoted_statement_is_declared(struct Denoted_Statement *statement)
+ {
+ return statement->statement!=NULL;
+ }
#endif
F diff --git a/src/semantics/identifiers/denoted.h b/src/semantics/identifiers/denoted.h
--- a/src/semantics/identifiers/denoted.h
+++ b/src/semantics/identifiers/denoted.h
void delete_denoted_base(struct Denoted_Base *base);
void delete_denoted_statement(struct Denoted_Statement *statement);
-
enum Storage_Class_Specifier get_denoted_function_storage_class(struct Denoted_Function *function);
+
+ _Bool denoted_statement_is_declared(struct Denoted_Statement *statement);
#endif
F diff --git a/src/semantics/identifiers/scope.c b/src/semantics/identifiers/scope.c
--- a/src/semantics/identifiers/scope.c
+++ b/src/semantics/identifiers/scope.c
return 1;
}
- void push_label(struct Scope *current,struct token *label,struct AST *statement,struct Translation_Data *translation_data)
+ struct Denoted* push_label(struct Scope *current,struct token *label,struct AST *statement,struct Translation_Data *translation_data)
{
struct Denoted_Statement *hold_statement;
struct Function_Scope *current_function_scope;
if(hold_statement->statement!=NULL)
{
push_translation_error("Redeclaration of label id %t",translation_data,label);
- return;
+
+ return get_denoted_error((struct Denoted*)hold_statement);
}else
{
assert(hold_statement->label!=NULL);
/*note the use of the current scope instead of the function scope*/
hold_statement->previous_denoted_object=get_last_known_denoted_object((struct Normal_Scope*)current);
- assert(hold_statement->previous_denoted_object->denotation==DT_Object);
+ assert(hold_statement->previous_denoted_object==NULL || hold_statement->previous_denoted_object->denotation==DT_Object);
+
+ return (struct Denoted*)hold_statement;
}
}else
{
hold_statement=(struct Denoted_Statement*)get_denoted_statement(label,statement,get_last_known_denoted_object((struct Normal_Scope*)current));
Map_Push(¤t_function_scope->labels,label->data,label->data_size,hold_statement);
+ Queue_Push(current_function_scope->label_order,hold_statement);
+
+
+ return (struct Denoted*)hold_statement;
}
+
+ assert(0);
}
F diff --git a/src/semantics/identifiers/scope.h b/src/semantics/identifiers/scope.h
--- a/src/semantics/identifiers/scope.h
+++ b/src/semantics/identifiers/scope.h
void* check_ordinary(struct Scope *current,struct token *id);
- void push_label(struct Scope *current,struct token *label,struct AST *statement,struct Translation_Data *translation_data);
+ /*
+ * a little bit different from the others because gotos can use forward declared labels
+ * so to not have a second passing of the ast we push the label with a null statement pointer
+ * when we 'declare' the label we push the label with a non null statement and get a constructed denoted statement
+ * that might have been made and pushed from a previous goto.
+ * A reference of all the gotos jumping to the label are held in the denoted statement struct so we can do
+ * constraint checking in the function definition constraint check ( that being if there are no variable length arrays be
+ * tween goto and label :X)
+ *
+ * CAN THROW A DENOTED ERROR IF THERE IS REDECLARATION!
+ *
+ * TODO refactor this into something more sensible
+ *
+ * */
+ struct Denoted* push_label(struct Scope *current,struct token *label,struct AST *statement,struct Translation_Data *translation_data);
+
void push_object(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Object *denoted_object);
void push_function(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Function *denoted_function);
void push_typedef(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Type *denoted_typedef);