/* 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); } struct def * lookup(id, scope) register struct idf *id; struct scope *scope; { /* Look up a definition of an identifier in scope "scope". Make the "def" list self-organizing. Return a pointer to its "def" structure if it exists, otherwise return 0. */ register struct def *df, *df1; struct def *retval; df1 = 0; df = id->id_def; while (df) { if (df->df_scope == scope) { retval = df; if (df->df_kind == D_IMPORT) { retval = df->imp_def; assert(retval != 0); } if (df1) { /* Put the definition now found in front */ df1->next = df->next; df->next = id->id_def; id->id_def = df; } return retval; } df1 = df; df = df->next; } return 0; } DoImport(df, scope) register struct def *df; struct scope *scope; { /* Definition "df" is imported to scope "scope". Handle the case that it is an enumeration type or a module. */ define(df->df_idf, scope, D_IMPORT)->imp_def = df; if (df->df_kind == D_TYPE && df->df_type->tp_fund == T_ENUMERATION) { /* Also import all enumeration literals */ df = df->df_type->enm_enums; while (df) { define(df->df_idf, scope, D_IMPORT)->imp_def = df; df = df->enm_next; } } else if (df->df_kind == D_MODULE) { /* Also import all definitions that are exported from this module */ df = df->mod_vis->sc_scope->sc_def; while (df) { if (df->df_flags & D_EXPORTED) { define(df->df_idf,scope,D_IMPORT)->imp_def = df; } df = df->df_nextinscope; } } } Export(ids, qualified, moddef) register struct node *ids; struct def *moddef; { /* From the current scope, the list of identifiers "ids" is exported. Note this fact. If the export is not qualified, make all the "ids" visible in the enclosing scope by defining them in this scope as "imported". */ register struct def *df, *df1; register struct def *impmod; for (;ids; ids = ids->next) { df = lookup(ids->nd_IDF, CurrentScope); if (!df) { /* undefined item in export list */ node_error(ids, "identifier \"%s\" not defined", ids->nd_IDF->id_text); continue; } if (df->df_flags & (D_EXPORTED|D_QEXPORTED)) { node_error(ids, "identifier \"%s\" occurs more than once in export list", df->df_idf->id_text); } if (qualified) { df->df_flags |= D_QEXPORTED; } else { /* Export, but not qualified. Find all imports of the module in which this export occurs, and export the current definition to it */ df->df_flags |= D_EXPORTED; impmod = moddef->df_idf->id_def; while (impmod) { if (impmod->df_kind == D_IMPORT && impmod->imp_def == moddef) { DoImport(df, impmod->df_scope); } impmod = impmod->next; } df1 = lookup(ids->nd_IDF, enclosing(CurrVis)->sc_scope); if (df1 && df1->df_kind == D_PROCHEAD) { if (df->df_kind == D_PROCEDURE) { df1->df_kind = D_IMPORT; df1->imp_def = df; continue; } } else if (df1 && df1->df_kind == D_HIDDEN) { if (df->df_kind == D_TYPE) { if (df->df_type->tp_fund != T_POINTER) { error("opaque type \"%s\" is not a pointer type", df->df_idf->id_text); } df->df_kind = D_TYPE; df1->df_kind = D_IMPORT; df1->imp_def = df; continue; } } DoImport(df, enclosing(CurrVis)->sc_scope); } } } static struct scopelist * ForwModule(df, idn) register struct def *df; struct node *idn; { /* An import is done from a not yet defined module "idn". Create a declaration and a scope for this module. */ struct scopelist *vis; df->df_scope = enclosing(CurrVis)->sc_scope; df->df_kind = D_FORWMODULE; open_scope(CLOSEDSCOPE); vis = CurrVis; /* The new scope, but watch out, it's "sc_encl" field is not set right. It must indicate the enclosing scope, but this must be done AFTER closing this one */ df->for_vis = vis; df->for_node = MkLeaf(Name, &(idn->nd_token)); close_scope(0); vis->sc_encl = enclosing(CurrVis); /* Here ! */ return vis; } static struct def * ForwDef(ids, scope) register struct node *ids; struct scope *scope; { /* Enter a forward definition of "ids" in scope "scope", if it is not already defined. */ register struct def *df; if (!(df = lookup(ids->nd_IDF, scope))) { df = define(ids->nd_IDF, scope, D_FORWARD); df->for_node = MkLeaf(Name, &(ids->nd_token)); } return df; } Import(ids, idn, local) register struct node *ids; struct node *idn; { /* "ids" is a list of imported identifiers. If "idn" is a null-pointer, the identifiers are imported from the enclosing scope. Otherwise they are imported from the module indicated by "idn", which must be visible in the enclosing scope. An exception must be made for imports of the Compilation Unit. This case is indicated by the value 0 of the flag "local". In this case, if "idn" is a null pointer, the "ids" identifiers are all module identifiers. Their Definition Modules must be read. Otherwise "idn" is a module identifier whose Definition Module must be read. "ids" then represents a list of identifiers defined in this module. */ register struct def *df; struct scopelist *vis = enclosing(CurrVis); int forwflag = 0; #define FROM_MODULE 0 #define FROM_ENCLOSING 1 int imp_kind = FROM_ENCLOSING; struct def *lookfor(), *GetDefinitionModule(); if (idn) { imp_kind = FROM_MODULE; if (local) { df = lookfor(idn, vis, 0); switch(df->df_kind) { case D_ERROR: /* The module from which the import was done is not yet declared. I'm not sure if I must accept this, but for the time being I will. ??? */ vis = ForwModule(df, idn); forwflag = 1; break; case D_FORWMODULE: vis = df->for_vis; break; case D_MODULE: vis = df->mod_vis; break; default: node_error(idn, "identifier \"%s\" does not represent a module", idn->nd_IDF->id_text); break; } } else vis = GetDefinitionModule(idn->nd_IDF)->mod_vis; FreeNode(idn); } idn = ids; while (ids) { if (imp_kind == FROM_MODULE) { if (forwflag) { df = ForwDef(ids, vis->sc_scope); } else if (!(df = lookup(ids->nd_IDF, vis->sc_scope))) { node_error(ids, "identifier \"%s\" not declared in qualifying module", ids->nd_IDF->id_text); df = define(ids->nd_IDF,vis->sc_scope,D_ERROR); } else if (!(df->df_flags&(D_EXPORTED|D_QEXPORTED))) { node_error(ids,"identifier \"%s\" not exported from qualifying module", ids->nd_IDF->id_text); df->df_flags |= D_QEXPORTED; } } else { if (local) df = ForwDef(ids, vis->sc_scope); else df = GetDefinitionModule(ids->nd_IDF); } DoImport(df, CurrentScope); ids = ids->next; } FreeNode(idn); } 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)); 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; } InitProc(nd, df) struct node *nd; struct def *df; { /* Create an initialization procedure for a module. */ df->mod_body = nd; /* Keep it this way, or really create a procedure out of it??? */ } 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; } } #ifdef DEBUG PrDef(df) register struct def *df; { print("n: %s, k: %d\n", df->df_idf->id_text, df->df_kind); } #endif DEBUG