/* D E F I N I T I O N M E C H A N I S M */ #ifndef NORCSID static char *RcsId = "$Header$"; #endif #include "debug.h" #include #include #include #include #include "main.h" #include "def.h" #include "type.h" #include "idf.h" #include "scope.h" #include "LLlex.h" #include "node.h" #include "Lpars.h" struct def *h_def; /* pointer to free list of def structures */ #ifdef DEBUG int cnt_def; /* count number of allocated ones */ #endif struct def *ill_df; struct def * MkDef(id, scope, kind) struct idf *id; register struct scope *scope; { /* Create a new definition structure in scope "scope", with id "id" and kind "kind". */ register struct def *df; df = new_def(); clear((char *) df, sizeof (*df)); df->df_idf = id; df->df_scope = scope; df->df_kind = kind; df->next = id->id_def; id->id_def = df; /* enter the definition in the list of definitions in this scope */ df->df_nextinscope = scope->sc_def; scope->sc_def = df; return df; } InitDef() { /* Initialize this module. Easy, the only thing to be initialized is "ill_df". */ struct idf *gen_anon_idf(); ill_df = MkDef(gen_anon_idf(), CurrentScope, D_ERROR); } struct def * define(id, scope, kind) register struct idf *id; register struct scope *scope; { /* Declare an identifier in a scope, but first check if it already has been defined. If so, error message. */ register struct def *df; df = lookup(id, scope); if ( /* Already in this scope */ df || /* A closed scope, and id defined in the pervasive scope */ ( scopeclosed(scope) && (df = lookup(id, PervasiveScope))) ) { switch(df->df_kind) { case D_HIDDEN: /* An opaque type. We may now have found the definition of this type. */ if (kind == D_TYPE && !DefinitionModule) { df->df_kind = D_TYPE; return df; } break; case D_FORWMODULE: /* A forward reference to a module. We may have found another one, or we may have found the definition for this module. */ if (kind == D_FORWMODULE) { return df; } if (kind == D_MODULE) { FreeNode(df->for_node); df->mod_vis = df->for_vis; df->df_kind = kind; DefInFront(df); return df; } break; case D_FORWARD: /* A forward reference, for which we may now have found a definition. */ if (kind != D_FORWARD) { FreeNode(df->for_node); } /* Fall through */ case D_ERROR: /* A definition generated by the compiler, because it found an error. Maybe, the user gives a definition after all. */ df->df_kind = kind; return df; } if (kind != D_ERROR) { /* Avoid spurious error messages */ error("identifier \"%s\" already declared", id->id_text); } return df; } return MkDef(id, scope, kind); } RemoveImports(pdf) struct def **pdf; { /* Remove all imports from a definition module. This is neccesary because the implementation module might import them again. */ register struct def *df = *pdf; while (df) { if (df->df_kind == D_IMPORT) { RemoveFromIdList(df); *pdf = df->df_nextinscope; free_def(df); } else { pdf = &(df->df_nextinscope); } df = *pdf; } } RemoveFromIdList(df) struct def *df; { /* Remove definition "df" from the definition list */ register struct idf *id = df->df_idf; register struct def *df1; if (id->id_def == df) id->id_def = df->next; else { df1 = id->id_def; while (df1->next != df) { assert(df1->next != 0); df1 = df1->next; } df1->next = df->next; } } struct def * DeclProc(type) { /* A procedure is declared, either in a definition or a program module. Create a def structure for it (if neccessary). Also create a name for it. */ register struct def *df; extern char *sprint(); static int nmcount; char buf[256]; assert(type & (D_PROCEDURE | D_PROCHEAD)); if (type == D_PROCHEAD) { /* In a definition module */ df = define(dot.TOK_IDF, CurrentScope, type); df->for_node = MkLeaf(Name, &dot); sprint(buf,"%s_%s",CurrentScope->sc_name,df->df_idf->id_text); df->for_name = Salloc(buf, (unsigned) (strlen(buf)+1)); if (CurrVis == Defined->mod_vis) C_exp(df->for_name); open_scope(OPENSCOPE); } else { df = lookup(dot.TOK_IDF, CurrentScope); if (df && df->df_kind == D_PROCHEAD) { /* C_exp already generated when we saw the definition in the definition module */ df->df_kind = D_PROCEDURE; open_scope(OPENSCOPE); CurrentScope->sc_name = df->for_name; df->prc_vis = CurrVis; DefInFront(df); } else { df = define(dot.TOK_IDF, CurrentScope, type); open_scope(OPENSCOPE); df->prc_vis = CurrVis; sprint(buf,"_%d_%s",++nmcount,df->df_idf->id_text); CurrentScope->sc_name = Salloc(buf, (unsigned)(strlen(buf)+1)); C_inp(buf); } } return df; } AddModule(id) struct idf *id; { /* Add the name of a module to the Module list. This list is maintained to create the initialization routine of the program/implementation module currently defined. */ static struct node *nd_end; /* to remember end of list */ register struct node *n; extern struct node *Modules; n = MkLeaf(Name, &dot); n->nd_IDF = id; n->nd_symb = IDENT; if (nd_end) nd_end->next = n; else Modules = n; nd_end = n; } DefInFront(df) register struct def *df; { /* Put definition "df" in front of the list of definitions in its scope. This is neccessary because in some cases the order in this list is important. */ register struct def *df1 = df->df_scope->sc_def; if (df1 != df) { /* Definition "df" is not in front of the list */ while (df1 && df1->df_nextinscope != df) { /* Find definition "df" */ df1 = df1->df_nextinscope; } if (df1) { /* It already was in the list. Remove it */ df1->df_nextinscope = df->df_nextinscope; } /* Now put it in front */ df->df_nextinscope = df->df_scope->sc_def; df->df_scope->sc_def = df; } } struct def * DefineLocalModule(id) struct idf *id; { /* Create a definition for a local module. Also give it a name to be used for code generation. */ register struct def *df = define(id, CurrentScope, D_MODULE); register struct type *tp; register struct scope *sc; static int modulecount = 0; char buf[256]; extern char *sprint(); extern int proclevel; sprint(buf, "_%d%s", ++modulecount, id->id_text); if (!df->mod_vis) { /* We never saw the name of this module before. Create a scope for it. */ open_scope(CLOSEDSCOPE); df->mod_vis = CurrVis; } CurrVis = df->mod_vis; sc = CurrentScope; sc->sc_level = proclevel; sc->sc_definedby = df; sc->sc_name = Salloc(buf, (unsigned) (strlen(buf) + 1)); /* Create a type for it */ df->df_type = tp = standard_type(T_RECORD, 0, (arith) 0); tp->rec_scope = sc; /* Generate code that indicates that the initialization procedure for this module is local. */ C_inp(buf); return df; } #ifdef DEBUG PrDef(df) register struct def *df; { print("n: %s, k: %d\n", df->df_idf->id_text, df->df_kind); } #endif DEBUG