#ifndef WONKY_SCOPE_H
#define WONKY_SCOPE_H WONKY_SCOPE_H
#include <scope.hh>
#include <map.h>
#include <denoted.h>
#include <memory_location.h>
#include <queue.h>
#include <constraints.h>
#include <common.h>
#include <identifier.h>
enum Scope_Type;
struct Scope
{
enum Scope_Type type;
struct Scope *parent;
};
struct Normal_Scope
{
enum Scope_Type type;
struct Scope *parent;
struct Map *tags;
struct Map *ordinary;
/*we need the object order for the unconditional jumps*/
struct Queue *object_order; /*queue of denoted objects*/
};
struct Function_Scope
{
enum Scope_Type type;
struct Scope *parent;
struct Denoted_Function *function;
struct Map *labels;
/*here to ease checking of undeclared but used labels*/
struct Queue *label_order; /*queue of denoted statements*/
};
struct Scope* get_normal_scope(struct Scope *parent,enum Scope_Type type);
struct Scope* get_partial_normal_scope(struct Normal_Scope *scope);
struct Scope* get_function_scope(struct Scope *parent,struct Denoted_Function *function);
struct Denoted_Statement* check_label(struct Scope *current,struct identifier *id);
struct Denoted* check_tag(struct Scope *current,struct identifier *id);
void* check_ordinary(struct Scope *current,struct identifier *id);
void* check_struct_union_member(struct Normal_Scope *inner,struct identifier *id);
/*
* 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 identifier *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);
void push_denoted_enum_tag(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Enum *denoted_enum);
void push_denoted_enum_constant(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Enum_Const *denoted_enum_constant);
void push_denoted_struct_union_tag(struct Scope *current,struct Translation_Data *translation_data,struct Denoted_Struct_Union *denoted_struct_union);
void Scope_Push(struct Scope *scope,struct Denoted *declarator,struct Translation_Data *translation_data);
struct Denoted_Function* get_enclosing_function(struct Scope *scope);
struct Function_Scope* get_enclosing_function_scope(struct Scope *scope);
struct Denoted_Object* get_last_known_denoted_object(struct Normal_Scope *scope);
void delete_scope(struct Scope *scope);
void delete_normal_scope(struct Normal_Scope *scope);
void delete_function_scope(struct Function_Scope *scope);
void* check_and_push_id(void *data,struct Map *scope_map,struct identifier *id,struct Translation_Data *translation_data);
_Bool check_if_typedefed(struct Scope* scope,struct identifier *id);
#endif