/kernel/symbol_table.c
https://bitbucket.org/raghavanSanthanam/cgdl · C · 622 lines · 510 code · 90 blank · 22 comment · 113 complexity · f1379911ee294752228f7effb7ddd984 MD5 · raw file
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "symbol_table.h"
- #define __DEBUG__
- #define NO_EXIT_ON_COMPILE_TIME_ERRORS
- #ifdef NO_EXIT_ON_COMPILE_TIME_ERRORS
- #define exit(exit_code)
- #endif // NO_EXIT_ON_COMPILE_TIME_ERRORS
- #ifdef __DEBUG__
- #define TOUCH() do {\
- printf("%s()\n", __func__);\
- } while ( 0 )
- #else
- #define TOUCH()
- #endif
- extern char *strdup(const char *s);
- extern bool comp_type_member_seen;
- extern bool comp_type_decln_seen;
- extern struct comp_type *last_seen_comp_type;
- extern char *src_file;
- extern int cur_comp_type_nesting_level;
- extern int active_block;
- extern bool last_member_is_comp_type;
- extern struct comp_type *last_seen_comp_type;
- struct comp_type_member *last_member;
- static struct comp_type_list *blocks_comp_type_lists[ EMax_nested_blocks +
- /* Global */1 ];
- static struct comp_type_list *comp_type_list_tails[ EMax_nested_blocks +
- /* Global */1 ];
- static struct symbol_list *blocks_symbol_lists[ EMax_nested_blocks +
- /* Global */1 ];
- static struct symbol_list *symbol_list_tails[ EMax_nested_blocks +
- /* Global */1 ];
- static struct func_type_list *global_func_type_list = NULL;
- static struct func_type_list *global_func_type_list_tail = NULL;
- static inline bool is_func_type_defined(struct func_type *f)
- {
- TOUCH();
- bool defined = false;
- struct func_type_list *t = global_func_type_list;
- while ( t ) {
- if ( !strcmp(t->f->name, f->name) ) {
- defined = true;
- }
- t = t->next;
- }
- return defined;
- }
- void display_func_types(void)
- {
- TOUCH();
- struct func_type_list *l = global_func_type_list;
- printf("Function types:\n");
- printf("- Return type - Name - Parameter list -\n");
- while ( l ) {
- struct func_type *f = l->f;
- printf("- %s - %s - %s -\n", f->ret_type, f->name,
- f->parameter_list);
- l = l->next;
- }
- }
- void add_func_type(struct func_type *f, unsigned long long int src_line)
- {
- TOUCH();
- static int t = 0;
- printf("%s called for %d time", __func__, ++t);
- if ( f ) {
- if ( !is_func_type_defined(f) ) {
- struct func_type_list *l = malloc(sizeof(*l));
- if ( l ) {
- l->f = f;
- l->next = NULL;
- }
- if ( global_func_type_list_tail ) {
- global_func_type_list_tail->next = l;
- } else {
- global_func_type_list = l;
- }
- global_func_type_list_tail = l;
- } else {
- struct term_or_nonterm tmp = { 0 };
- tmp.src_line = src_line; // Don't bother about other
- // fields.
- void *trans_node = &tmp; // To allow below macro
- // think it has a trans_node indeed
- // to extract the src_line from --
- // uniformity concern!
- COMPILATION_ERROR("Refinition of function %s\n",
- f->name);
- }
- }
- }
- void add_comp_type(char *t, unsigned long long int src_line)
- {
- TOUCH();
- if ( !t ) {
- return; // Huh, too much of indentation otherwise! :P
- }
- if ( cur_comp_type_nesting_level == EMax_comp_type_nesting_limit ) {
- struct term_or_nonterm tmp = { 0 };
- tmp.src_line = src_line; // Don't bother about other
- // fields.
- void *trans_node = &tmp; // To allow below macro
- // think it has a trans_node indeed
- // to extract the src_line from --
- // uniformity concern!
- COMPILATION_ERROR
- ("Sorry! Maximum nesting limit %d exceeded!\n",
- EMax_comp_type_nesting_limit);
- }
- if ( comp_type_decln_seen ) {
- if ( last_seen_comp_type ) {
- if ( !strcmp(last_seen_comp_type->tag, t) ) {
- struct term_or_nonterm tmp = { 0 };
- tmp.src_line = src_line; // Don't bother
- // about other fields.
- void *trans_node = &tmp; // To allow below macro
- // think it has a trans_node indeed
- // to extract the src_line from --
- // uniformity concern!
- COMPILATION_ERROR("%s already "
- "defined as %s\n",
- t, last_seen_comp_type->tag);
- }
- }
- } else {
- struct comp_type_list *l =
- blocks_comp_type_lists[ active_block ];
- while ( l ) {
- if ( !strcmp(l->c->tag, t) ) {
- struct term_or_nonterm tmp = { 0 };
- tmp.src_line = src_line; // Don't bother
- // about other fields.
- void *trans_node = &tmp; // To allow below macro
- // think it has a trans_node indeed
- // to extract the src_line from --
- // uniformity concern!
- COMPILATION_ERROR("%s already "
- "defined as %s\n", t,
- l->c->tag);
- }
- l = l->next;
- }
- }
- struct comp_type *c = malloc(sizeof(*c));
- if ( c ) {
- c->tag = strdup(t);
- c->m = NULL;
- c->inst = NULL;
- if ( !comp_type_member_seen) {
- struct comp_type_list *l = malloc(sizeof(*l));
- if ( l ) {
- l->c = c;
- l->next = NULL;
- if ( comp_type_list_tails[ active_block ] ) {
- comp_type_list_tails
- [ active_block ]->next = l;
- } else {
- blocks_comp_type_lists
- [ active_block ] = l;
- }
- comp_type_list_tails[ active_block ] = l;
- last_seen_comp_type = c;
- cur_comp_type_nesting_level++;
- } else {
- free(c->tag);
- c->tag = NULL;
- free(c);
- c = NULL;
- }
- } else {
- struct comp_type_member *m = malloc(sizeof(*m));
- if ( m ) {
- m->type = EComps;
- m->f.c = c;
- m->next = NULL;
- if ( last_member ) {
- last_member->next = m;
- } else {
- last_member = last_seen_comp_type->m = m;
- }
- cur_comp_type_nesting_level++;
- } else {
- free(c->tag);
- c->tag = NULL;
- free(c);
- c = NULL;
- }
- }
- }
- }
- inline bool is_var_defined(char *v)
- {
- TOUCH();
- bool defined = false;
- int i = active_block;
- while ( i >= 0 ) {
- struct symbol_list *l = blocks_symbol_lists[ i ];
- while ( l ) {
- if ( !strcmp(l->s->n, v) ) {
- defined = true;
- break;
- }
- l = l->next;
- }
- if ( defined ) {
- break;
- }
- i--;
- }
- return defined;
- }
- static inline bool is_var_defined_already_in_current_scope(char *v, char **e_t)
- {
- TOUCH();
-
- bool defined = false;
- struct symbol_list *l = blocks_symbol_lists[ active_block ];
- while ( l ) {
- if ( !strcmp(l->s->n, v) ) {
- *e_t = l->s->t;
- defined = true;
- break;
- }
- l = l->next;
- }
- return defined;
- }
- static void display_comp_type(struct comp_type *c, int p_tabs)
- {
- TOUCH();
- int n_tabs = 1;
- printf("record(%p) %s {\n", (void *)c, c->tag);
- struct comp_type_member *m = c->m;
- while ( m ) {
- if ( m->type == ESymbol ) {
- int t = n_tabs + p_tabs;
- while ( t-- ) {
- putchar('\t');
- }
- printf("%s %s;\n", m->f.s->t, m->f.s->n);
- } else if ( m->type == EComps ) {
- n_tabs++;
- int t = n_tabs + p_tabs;
- while ( t-- ) {
- putchar('\t');
- }
- display_comp_type(m->f.c, n_tabs);
- n_tabs--;
- }
- m = m->next;
- }
- printf("};\n");
- }
- void display_current_block_symbol_table(void)
- {
- TOUCH();
- printf("active_block : %d\n", active_block);
- struct symbol_list *l = blocks_symbol_lists[ active_block ];
- printf("l : %p\n", (void *)l);
- printf("Symbol list for the block : %d\n", active_block);
- printf("| type | name |\n");
- while ( l ) {
- printf("| %s | %s |\n", l->s->t, l->s->n);
- l = l->next;
- }
- printf("Comp type list for the block : %d\n", active_block);
- struct comp_type_list *c = blocks_comp_type_lists[ active_block ];
- if ( c ) {
- while ( c ) {
- int n_tabs = 0;
- display_comp_type(c->c, n_tabs);
- c = c->next;
- }
- }
- }
- void display_current_and_enlcosing_block_symbol_table(void)
- {
- TOUCH();
- int b = active_block;
- while ( b >= 0 ) {
- printf("Symbol list for the block : %d\n", b);
- printf("| type | name |\n");
- struct symbol_list *l = blocks_symbol_lists[ b ];
- while ( l ) {
- printf("| %s | %s |\n", l->s->t, l->s->n);
- l = l->next;
- }
- b--;
- }
-
- }
- void display_all_blocks_symbol_table(void)
- {
- TOUCH();
- int i = 0;
- while ( i < EMax_nested_blocks ) {
- printf("Symbol list for the block : %d\n", i);
- printf("| type | name |\n");
- struct symbol_list *l = blocks_symbol_lists[ i ];
- while ( l ) {
- printf("| %s | %s |\n", l->s->t, l->s->n);
- l = l->next;
- }
- i++;
- }
- }
- void free_symbol_list(int b)
- {
- TOUCH();
- if ( b >= 0 && b < EMax_nested_blocks ) {
- struct symbol_list *l = blocks_symbol_lists[ b ];
- while ( l ) {
- struct symbol_list *next = l->next;
- free(l->s);
- l->s = NULL;
- free(l);
- l = next;
- }
- blocks_symbol_lists[ b ] = NULL;
- symbol_list_tails[ b ] = NULL;
- }
- }
- void add_symbol(struct unified_type *t,
- unsigned long long int src_line)
- {
- TOUCH();
- if ( t ) {
- char *v = t->type == EComp ? t->u.c->tag : t->u.s->n;
- char *e_t = NULL;
- if ( is_var_defined_already_in_current_scope(v, &e_t) ) {
- struct term_or_nonterm tmp = { 0 };
- tmp.src_line = src_line; // Don't bother about other
- // fields.
- void *trans_node = &tmp; // To allow below macro
- // think it has a trans_node indeed
- // to extract the src_line from --
- // uniformity concern!
- COMPILATION_ERROR("%s already defined as %s\n", v, e_t);
- }
-
- if ( last_member_is_comp_type && last_seen_comp_type ) {
- last_seen_comp_type->inst = t->u.c->inst;
- return; // Duh, I am not gonna indent any more
- // deep! :P
- }
- struct symbol *sym = malloc(sizeof(*sym));
- if ( sym ) {
- char *n = t->type == EComp ? t->u.c->inst : t->u.s->n;
- strncpy(sym->n, n, ESignificant_identifier_len);
- printf("sym->n : %s\n", sym->n);
- sym->t = strdup(t->type == EComp ? t->u.c->tag : t->u.s->t);
- struct symbol_list *le = malloc(sizeof(*le));
- if ( !comp_type_decln_seen ) {
- if ( le ) {
- le->s = sym;
- le->next = NULL;
- if (symbol_list_tails
- [ active_block ] ) {
- symbol_list_tails
- [ active_block ]->next = le;
- printf("1: Symbol added!\n");
-
- printf("after adding - blocks_symbol_lists"
- "[ active_block ] : %p\n",
- (void *)blocks_symbol_lists
- [ active_block ]);
- } else {
- blocks_symbol_lists
- [ active_block ] = le;
- printf("2: Symbol added!\n");
- }
- symbol_list_tails
- [ active_block ] = le;
- } else {
- free(sym->t);
- sym->t = NULL;
- free(sym);
- sym = NULL;
- }
- } else {
- struct comp_type_member *m =
- malloc(sizeof(*m));
- if ( m ) {
- m->type = ESymbol;
- m->f.s = sym;
- m->next = NULL;
- if ( last_member ) {
- last_member->next = m;
- } else {
- last_member =
- last_seen_comp_type
- ->m = m;
- }
- last_member = m;
- } else {
- free(sym->t);
- sym->t = NULL;
- free(sym);
- sym = NULL;
- }
- }
- }
- }
- }
- // Intended for checking user defined type.
- inline bool is_type_defined(char *n)
- {
- TOUCH();
- bool defined = false;
- if ( n ) {
- struct comp_type_list *l =
- blocks_comp_type_lists[ active_block ];
- while ( l ) {
- if ( !strcmp(l->c->inst, n) ) {
- defined = true;
- break;
- }
- l = l->next;
- }
- }
- return defined;
- }
- inline bool is_comp_type_member_defined(char *m_name,
- struct comp_type *c)
- {
- TOUCH();
- if ( !m_name || !c ) {
- return false;
- }
- bool defined = false;
- struct comp_type_member *m = c->m;
- while ( m ) {
- if ( (m->f.s->n && !strcmp(m->f.s->n, m_name)) ||
- (m->f.c->inst && !strcmp(m->f.c->inst, m_name)) ) {
- defined = true;
- break;
- }
- m = m->next;
- }
- return defined;
- }
- struct unified_type *type_of(char *v, struct unified_type *parent)
- {
- TOUCH();
- if ( !v ) {
- return NULL;
- }
- struct unified_type *u = NULL;
- if ( !parent ) {
- bool defined = false;
- int i = active_block;
- while ( i >= 0 ) {
- struct symbol_list *l = blocks_symbol_lists[ i ];
- while ( l ) {
- printf("Block[ %d ] : %s\n", i, l->s->n);
- if ( !strcmp(l->s->n, v) ) {
- u = malloc(sizeof(*u));
- if ( u ) {
- u->type = EBasic;
- u->u.s = l->s;
- }
- defined = true;
- break;
- }
- l = l->next;
- }
- if ( defined ) {
- break;
- }
- i--;
- }
- } else {
- if ( parent->type == EComp ) {
- struct comp_type_member *m = parent->u.c->m;
- while ( m ) {
- if ( m->type == EComp &&
- !strcmp(m->f.c->inst, v) ) {
- u = malloc(sizeof(*u));
- if ( u ) {
- u->type = EComp;
- u->u.c = m->f.c;
- }
- } else if ( m->type == EBasic &&
- !strcmp(m->f.s->n, v) ) {
- u = malloc(sizeof(*u));
- if ( u ) {
- u->type = EBasic;
- u->u.s = m->f.s;
- }
- }
- m = m->next;
- }
- }
- }
- return u;
- }
- struct unified_type *unification(char *t, char *v, int type)
- {
- TOUCH();
- struct unified_type *u = NULL;
- if ( !t || (!v && type == EBasic) ) {
- return u;
- }
- u = malloc(sizeof(*u));
- if ( u ) {
- u->type = type;
- if ( type == EBasic ) {
- u->u.s = malloc(sizeof(*u->u.s));
- if ( u->u.s ) {
- strcpy(u->u.s->n, v);
- u->u.s->t = strdup(t);
- }
- } else if ( type == EComp ) {
- u->u.c = malloc(sizeof(*u->u.c));
- if ( u->u.c ) {
- u->u.c->tag = strdup(t);
- if ( v ) {
- u->u.c->inst = strdup(v);
- }
- u->u.c->m = NULL;
- }
- }
- }
-
- return u;
- }
- void free_symbol_lists(void)
- {
- TOUCH();
- int i = 0;
- while ( i < EMax_nested_blocks + 1 ) {
- free_symbol_list(i);
- i++;
- }
- }