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;
}
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 */
#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;
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);
}
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) {
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;
[ %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.
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!
}
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;
}
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 *
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);
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;
}
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);
{
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;
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) ||
}
} 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;
}