From f1245e2e00153331163be06481ffa4e03466a286 Mon Sep 17 00:00:00 2001 From: ceriel Date: Tue, 15 Nov 1988 14:45:59 +0000 Subject: [PATCH] fixed some problems: - removed null-reference in illegal use of pointers in constant expressions - FOR-loops that count downwards did not work - POINTER TO mechanism changed; works better now --- lang/m2/comp/chk_expr.c | 3 +- lang/m2/comp/def.H | 5 +-- lang/m2/comp/def.c | 5 +-- lang/m2/comp/enter.c | 5 ++- lang/m2/comp/program.g | 1 + lang/m2/comp/scope.C | 28 ++-------------- lang/m2/comp/type.c | 74 ++++++++++++++++++++++++++++++++++++----- lang/m2/comp/walk.c | 14 +++++--- 8 files changed, 86 insertions(+), 49 deletions(-) diff --git a/lang/m2/comp/chk_expr.c b/lang/m2/comp/chk_expr.c index a5c891659..68f755fdc 100644 --- a/lang/m2/comp/chk_expr.c +++ b/lang/m2/comp/chk_expr.c @@ -161,7 +161,8 @@ ChkArrow(expp) return ex_error(expp, "illegal operand type"); } - expp->nd_type = RemoveEqual(PointedtoType(tp)); + if ((tp = RemoveEqual(PointedtoType(tp))) == 0) tp = error_type; + expp->nd_type = tp; return 1; } diff --git a/lang/m2/comp/def.H b/lang/m2/comp/def.H index b9c49038f..0b93ce6fa 100644 --- a/lang/m2/comp/def.H +++ b/lang/m2/comp/def.H @@ -71,7 +71,9 @@ struct dforward { struct forwtype { struct node *f_node; + struct def *f_def; #define df_forw_node df_value.df_fortype.f_node +#define df_forw_def df_value.df_fortype.f_def }; struct def { /* list of definitions for a name */ @@ -94,14 +96,13 @@ struct def { /* list of definitions for a name */ #define D_FORWARD 0x0400 /* not yet defined */ #define D_FORWMODULE 0x0800 /* module must be declared later */ #define D_FORWTYPE 0x1000 /* forward type */ -#define D_FTYPE 0x2000 /* resolved forward type */ #define D_ERROR 0x4000 /* a compiler generated definition for an undefined variable */ #define D_INUSE 0x8000 /* identification in this scope (like D_IMPORT) */ #define D_VALUE (D_PROCEDURE|D_VARIABLE|D_FIELD|D_ENUM|D_CONST|D_PROCHEAD) -#define D_ISTYPE (D_HIDDEN|D_TYPE|D_FTYPE) +#define D_ISTYPE (D_HIDDEN|D_TYPE) #define D_IMPORTED (D_IMPORT|D_INUSE) #define is_type(dfx) ((dfx)->df_kind & D_ISTYPE) unsigned short df_flags; diff --git a/lang/m2/comp/def.c b/lang/m2/comp/def.c index dd92ef75d..260f2c560 100644 --- a/lang/m2/comp/def.c +++ b/lang/m2/comp/def.c @@ -157,10 +157,7 @@ define(id, scope, kind) if (kind == D_FORWTYPE) return df; break; case D_FORWTYPE: - if (kind == D_FORWTYPE) return df; - if (kind == D_TYPE) { - df->df_kind = D_FTYPE; - } + if (kind & (D_FORWTYPE|D_TYPE)) return df; else { error("identifier \"%s\" must be a type", id->id_text); diff --git a/lang/m2/comp/enter.c b/lang/m2/comp/enter.c index cca0e24ac..6994d414f 100644 --- a/lang/m2/comp/enter.c +++ b/lang/m2/comp/enter.c @@ -251,8 +251,7 @@ ImportEffects(idef, scope, flag) } tp = BaseType(df->df_type); - if ((df->df_kind & (D_TYPE|D_FTYPE)) && - tp->tp_fund == T_ENUMERATION) { + if (df->df_kind == D_TYPE && tp->tp_fund == T_ENUMERATION) { /* Also import all enumeration literals */ for (df = tp->enm_enums; df; df = df->enm_next) { @@ -416,7 +415,7 @@ EnterExportList(Idlist, qualified) continue; } if (df1->df_kind == D_HIDDEN && - (df2->df_kind & (D_TYPE|D_FTYPE))) { + df2->df_kind == D_TYPE) { DeclareType(idlist, df1, df2->df_type); df1->df_kind = D_TYPE; continue; diff --git a/lang/m2/comp/program.g b/lang/m2/comp/program.g index b2d85a30e..1e98a3eff 100644 --- a/lang/m2/comp/program.g +++ b/lang/m2/comp/program.g @@ -189,6 +189,7 @@ definition [ %persistent IDENT { df = define(dot.TOK_IDF, CurrentScope, D_TYPE); } [ '=' type(&(df->df_type)) + { SolveForwardTypeRefs(df); } | /* empty */ /* Here, the exported type has a hidden implementation. diff --git a/lang/m2/comp/scope.C b/lang/m2/comp/scope.C index fcd976c4f..5ca972a5f 100644 --- a/lang/m2/comp/scope.C +++ b/lang/m2/comp/scope.C @@ -109,34 +109,10 @@ chk_forw(pdf) while (df = *pdf) { if (df->df_kind == D_FORWTYPE) { - register t_def *df1 = df; - register t_node *nd = df->df_forw_node; - - *pdf = df->df_nextinscope; - RemoveFromIdList(df); - df = lookfor(nd, CurrVis, 1, 0); - if (! df->df_kind & (D_ERROR|D_FTYPE|D_TYPE)) { -node_error(nd, "\"%s\" is not a type", df1->df_idf->id_text); - } - while (nd) { - nd->nd_type->tp_next = df->df_type; - nd = nd->nd_right; - } - FreeNode(df1->df_forw_node); - free_def(df1); + ForceForwardTypeDef(df); /* removes df */ continue; } - else if (df->df_kind == D_FTYPE) { - register t_node *nd = df->df_forw_node; - - df->df_kind = D_TYPE; - while (nd) { - nd->nd_type->tp_next = df->df_type; - nd = nd->nd_right; - } - FreeNode(df->df_forw_node); - } - else if (df->df_kind & (D_FORWARD|D_FORWMODULE)) { + if (df->df_kind & (D_FORWARD|D_FORWMODULE)) { /* These definitions must be found in the enclosing closed scope, which of course may be the scope that is now closed! diff --git a/lang/m2/comp/type.c b/lang/m2/comp/type.c index 6a78627e1..265ce7f90 100644 --- a/lang/m2/comp/type.c +++ b/lang/m2/comp/type.c @@ -269,7 +269,11 @@ node_error(nd,"type \"%s\" not (yet) declared", df->df_idf->id_text); } FreeNode(nd); if (df->df_kind == D_FORWTYPE) { - df->df_kind = D_FTYPE; + /* Here, df->df_type was already set, + so there is an actual definition in the + surrounding scope, which is now used. + */ + ForceForwardTypeDef(df); } return df->df_type; } @@ -646,6 +650,58 @@ DeclareType(nd, df, tp) CheckForImports(df); } } + + SolveForwardTypeRefs(df); +} + +SolveForwardTypeRefs(df) + register t_def *df; +{ + register t_node *nd; + + if (df->df_kind == D_FORWTYPE) { + nd = df->df_forw_node; + + df->df_kind = D_TYPE; + while (nd) { + nd->nd_type->tp_next = df->df_type; + nd = nd->nd_right; + } + FreeNode(df->df_forw_node); + } +} + + +ForceForwardTypeDef(df) + register t_def *df; +{ + register t_def *df1 = df, *df2; + register t_node *nd = df->df_forw_node; + + while (df && df->df_kind == D_FORWTYPE) { + RemoveFromIdList(df); + if ((df2 = df->df_scope->sc_def) == df) { + df->df_scope->sc_def = df->df_nextinscope; + } + else { + while (df2->df_nextinscope != df) { + df2 = df2->df_nextinscope; + } + df2->df_nextinscope = df->df_nextinscope; + } + df = df->df_forw_def; + } + df = lookfor(nd, CurrVis, 1, 0); + if (! df->df_kind & (D_ERROR|D_TYPE)) { + node_error(nd, "\"%s\" is not a type", df1->df_idf->id_text); + } + while (df1 && df1->df_kind == D_FORWTYPE) { + t_def *df2 = df1->df_forw_def; + df1->df_type = df->df_type; + SolveForwardTypeRefs(df1); + free_def(df1); + df1 = df2; + } } t_type * @@ -686,6 +742,8 @@ type_or_forward(ptp) existing compilers do it like this, and the alternative is difficult with a lookahead of only one token. + This path should actually only be taken if the next token + is a '.'. ??? */ FreeNode(nd); @@ -697,17 +755,17 @@ type_or_forward(ptp) same scope. */ df = define(nd->nd_IDF, CurrentScope, D_FORWTYPE); + assert(df->df_kind == D_FORWTYPE); df->df_flags |= D_USED | D_DEFINED; - - if (df->df_kind == D_TYPE) { - (*ptp)->tp_next = df->df_type; - FreeNode(nd); - return 0; - } nd->nd_type = *ptp; df->df_forw_node = nd; - if (df1->df_kind == D_TYPE) { + if (df != df1 && (df1->df_kind & (D_TYPE | D_FORWTYPE))) { + /* "df1" refers to a possible identification, but + we cannot be sure at this point. For the time + being, however, we use this one. + */ df->df_type = df1->df_type; + df->df_forw_def = df1; } return 0; } diff --git a/lang/m2/comp/walk.c b/lang/m2/comp/walk.c index 28a52f83b..29f2ec42b 100644 --- a/lang/m2/comp/walk.c +++ b/lang/m2/comp/walk.c @@ -552,8 +552,10 @@ WalkStat(nd, exit_label) C_lol(tmp); if (uns) C_cmu(int_size); else C_cmi(int_size); - C_zgt(l2); + if (left->nd_INT >= 0) C_zgt(l2); + else C_zlt(l2); C_lol(tmp2); + RangeCheck(nd->nd_type, left->nd_left->nd_type); CodeDStore(nd); C_lol(tmp); ForLoopVarExpr(nd); @@ -736,6 +738,7 @@ DoForInit(nd) { register t_node *left = nd->nd_left; register t_def *df; + register t_type *base_tp; t_type *tpl, *tpr; nd->nd_left = nd->nd_right = 0; @@ -778,12 +781,13 @@ DoForInit(nd) return 1; } + base_tp = BaseType(df->df_type); tpl = left->nd_left->nd_type; tpr = left->nd_right->nd_type; #ifndef STRICT_3RD_ED if (! options['3']) { - if (!ChkAssCompat(&(left->nd_left), df->df_type, "FOR statement") || - !ChkAssCompat(&(left->nd_right), BaseType(df->df_type), "FOR statement")) { + if (!ChkAssCompat(&(left->nd_left), base_tp, "FOR statement") || + !ChkAssCompat(&(left->nd_right), base_tp, "FOR statement")) { return 1; } if (!TstCompat(df->df_type, tpl) || @@ -792,8 +796,8 @@ node_warning(nd, W_OLDFASHIONED, "compatibility required in FOR statement"); } } else #endif - if (!ChkCompat(&(left->nd_left), df->df_type, "FOR statement") || - !ChkCompat(&(left->nd_right), BaseType(df->df_type), "FOR statement")) { + if (!ChkCompat(&(left->nd_left), base_tp, "FOR statement") || + !ChkCompat(&(left->nd_right), base_tp, "FOR statement")) { return 1; } -- 2.34.1