From: ceriel Date: Tue, 22 Apr 1986 22:36:16 +0000 (+0000) Subject: newer version X-Git-Tag: release-5-5~5302 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=fef8659bf1ae6ef63cb627b45927e848397af90b;p=ack.git newer version --- diff --git a/lang/m2/comp/LLlex.c b/lang/m2/comp/LLlex.c index 1cf3c3877..a252b606d 100644 --- a/lang/m2/comp/LLlex.c +++ b/lang/m2/comp/LLlex.c @@ -182,7 +182,7 @@ again: } else if (nch == '>') { - return tk->tk_symb = UNEQUAL; + return tk->tk_symb = '#'; } PushBack(nch); return tk->tk_symb = ch; @@ -219,7 +219,9 @@ again: case STSTR: GetString(ch); - tk->tk_data.tk_str = string; + tk->tk_data.tk_str = (struct string *) + Malloc(sizeof (struct string)); + *(tk->tk_data.tk_str) = string; return tk->tk_symb = STRING; case STNUM: diff --git a/lang/m2/comp/LLlex.h b/lang/m2/comp/LLlex.h index 16ea9e010..69573dd00 100644 --- a/lang/m2/comp/LLlex.h +++ b/lang/m2/comp/LLlex.h @@ -13,7 +13,7 @@ struct token { int tk_lineno; /* linenumber on which it occurred */ union { struct idf *tk_idf; /* IDENT */ - struct string tk_str; /* STRING */ + struct string *tk_str; /* STRING */ arith tk_int; /* INTEGER */ char *tk_real; /* REAL */ arith *tk_set; /* only used in parse tree node */ @@ -22,8 +22,8 @@ struct token { }; #define TOK_IDF tk_data.tk_idf -#define TOK_STR tk_data.tk_str.s_str -#define TOK_SLE tk_data.tk_str.s_length +#define TOK_STR tk_data.tk_str->s_str +#define TOK_SLE tk_data.tk_str->s_length #define TOK_INT tk_data.tk_int #define TOK_REL tk_data.tk_real diff --git a/lang/m2/comp/Makefile b/lang/m2/comp/Makefile index 6b2a4d735..708158581 100644 --- a/lang/m2/comp/Makefile +++ b/lang/m2/comp/Makefile @@ -82,12 +82,12 @@ LLlex.o: LLlex.h Lpars.h class.h const.h f_info.h idf.h idfsize.h input.h inputt LLmessage.o: LLlex.h Lpars.h idf.h char.o: class.h error.o: LLlex.h debug.h errout.h f_info.h input.h inputtype.h main.h node.h -main.o: LLlex.h Lpars.h debug.h def.h f_info.h idf.h input.h inputtype.h scope.h standards.h tokenname.h type.h +main.o: LLlex.h Lpars.h debug.h def.h f_info.h idf.h input.h inputtype.h node.h scope.h standards.h tokenname.h type.h symbol2str.o: Lpars.h tokenname.o: Lpars.h idf.h tokenname.h idf.o: idf.h input.o: f_info.h input.h inputtype.h -type.o: LLlex.h const.h debug.h def.h idf.h node.h target_sizes.h type.h +type.o: LLlex.h const.h debug.h def.h idf.h maxset.h node.h target_sizes.h type.h def.o: LLlex.h debug.h def.h idf.h main.h node.h scope.h type.h scope.o: LLlex.h debug.h def.h idf.h node.h scope.h type.h misc.o: LLlex.h f_info.h idf.h misc.h node.h @@ -98,10 +98,10 @@ node.o: LLlex.h debug.h def.h node.h type.h cstoper.o: LLlex.h Lpars.h idf.h node.h standards.h target_sizes.h type.h chk_expr.o: LLlex.h Lpars.h const.h debug.h def.h idf.h node.h scope.h standards.h type.h options.o: idfsize.h type.h -walk.o: debug.h def.h main.h scope.h type.h +walk.o: LLlex.h Lpars.h debug.h def.h main.h node.h scope.h type.h tokenfile.o: Lpars.h program.o: LLlex.h Lpars.h debug.h def.h idf.h main.h node.h scope.h type.h declar.o: LLlex.h Lpars.h def.h idf.h main.h misc.h node.h scope.h type.h expression.o: LLlex.h Lpars.h const.h debug.h def.h idf.h node.h scope.h type.h -statement.o: LLlex.h Lpars.h node.h type.h +statement.o: LLlex.h Lpars.h def.h idf.h node.h scope.h type.h Lpars.o: Lpars.h diff --git a/lang/m2/comp/Parameters b/lang/m2/comp/Parameters index f49d2aad8..fcdfc05c9 100644 --- a/lang/m2/comp/Parameters +++ b/lang/m2/comp/Parameters @@ -58,3 +58,9 @@ extern char options[]; #undef INP_READ_IN_ONE 1 /* read input file in one */ +!File: maxset.h +#define MAXSET 1024 /* maximum number of elements in a set, + but what is a reasonable choice ??? + */ + + diff --git a/lang/m2/comp/chk_expr.c b/lang/m2/comp/chk_expr.c index 6c950e5bd..bf9c58c34 100644 --- a/lang/m2/comp/chk_expr.c +++ b/lang/m2/comp/chk_expr.c @@ -63,6 +63,7 @@ chk_expr(expp) case Link: return chk_name(expp); + default: assert(0); } @@ -85,32 +86,42 @@ chk_set(expp) /* First determine the type of the set */ - if (expp->nd_left) { + if (nd = expp->nd_left) { /* A type was given. Check it out */ - findname(expp->nd_left); - assert(expp->nd_left->nd_class == Def); - df = expp->nd_left->nd_def; + findname(nd); + assert(nd->nd_class == Def); + df = nd->nd_def; + if (!(df->df_kind & (D_TYPE|D_ERROR)) || (df->df_type->tp_fund != T_SET)) { - node_error(expp, "illegal set type"); + node_error(expp, "specifier does not represent a set type"); return 0; } tp = df->df_type; + FreeNode(expp->nd_left); + expp->nd_left = 0; } else tp = bitset_type; /* Now check the elements given, and try to compute a constant set. + First allocate room for the set */ set = (arith *) Malloc((unsigned) (tp->tp_size * sizeof(arith) / word_size)); + + /* Now check the elements, one by one + */ nd = expp->nd_right; while (nd) { assert(nd->nd_class == Link && nd->nd_symb == ','); + if (!chk_el(nd->nd_left, tp->next, &set)) return 0; nd = nd->nd_right; } + expp->nd_type = tp; + if (set) { /* Yes, it was a constant set, and we managed to compute it! Notice that at the moment there is no such thing as @@ -119,10 +130,10 @@ chk_set(expp) */ expp->nd_class = Set; expp->nd_set = set; - FreeNode(expp->nd_left); FreeNode(expp->nd_right); - expp->nd_left = expp->nd_right = 0; + expp->nd_right = 0; } + return 1; } @@ -137,35 +148,38 @@ chk_el(expp, tp, set) Also try to compute the set! */ register int i; + register struct node *left = expp->nd_left; + register struct node *right = expp->nd_right; if (expp->nd_class == Link && expp->nd_symb == UPTO) { /* { ... , expr1 .. expr2, ... } First check expr1 and expr2, and try to compute them. */ - if (!chk_el(expp->nd_left, tp, set) || - !chk_el(expp->nd_right, tp, set)) { + if (!chk_el(left, tp, set) || !chk_el(right, tp, set)) { return 0; } - if (expp->nd_left->nd_class == Value && - expp->nd_right->nd_class == Value) { + + if (left->nd_class == Value && right->nd_class == Value) { /* We have a constant range. Put all elements in the set */ - if (expp->nd_left->nd_INT > expp->nd_right->nd_INT) { + if (left->nd_INT > right->nd_INT) { node_error(expp, "lower bound exceeds upper bound in range"); return rem_set(set); } - - if (*set) for (i = expp->nd_left->nd_INT + 1; - i < expp->nd_right->nd_INT; i++) { - (*set)[i/wrd_bits] |= (1 << (i % wrd_bits)); + + if (*set) { + for (i=left->nd_INT+1; ind_INT; i++) { + (*set)[i/wrd_bits] |= (1<<(i%wrd_bits)); + } } } else if (*set) { free((char *) *set); *set = 0; } + return 1; } @@ -174,12 +188,17 @@ node_error(expp, "lower bound exceeds upper bound in range"); if (!chk_expr(expp)) { return rem_set(set); } + if (!TstCompat(tp, expp->nd_type)) { node_error(expp, "set element has incompatible type"); return rem_set(set); } + if (expp->nd_class == Value) { + /* a constant element + */ i = expp->nd_INT; + if ((tp->tp_fund != T_ENUMERATION && (i < tp->sub_lb || i > tp->sub_ub)) || @@ -189,8 +208,10 @@ node_error(expp, "lower bound exceeds upper bound in range"); node_error(expp, "set element out of range"); return rem_set(set); } + if (*set) (*set)[i/wrd_bits] |= (1 << (i%wrd_bits)); } + return 1; } @@ -552,7 +573,7 @@ findname(expp) expp->nd_type = df->df_type; if (!(df->df_flags & (D_EXPORTED|D_QEXPORTED))) { node_error(expp->nd_right, -"identifier \"%s\" not exprted from qualifying module", +"identifier \"%s\" not exported from qualifying module", df->df_idf->id_text); } } @@ -723,6 +744,7 @@ node_error(expp, "IN operator: type of LHS not compatible with element type of R case OR: case AND: + case '&': if (tpl == bool_type) { if (expp->nd_left->nd_class == Value && expp->nd_right->nd_class == Value) { @@ -735,10 +757,12 @@ node_error(expp, "IN operator: type of LHS not compatible with element type of R case '=': case '#': + case UNEQUAL: case GREATEREQUAL: case LESSEQUAL: case '<': case '>': + expp->nd_type = bool_type; switch(tpl->tp_fund) { case T_SET: if (expp->nd_symb == '<' || expp->nd_symb == '>') { @@ -762,10 +786,10 @@ node_error(expp, "IN operator: type of LHS not compatible with element type of R return 1; case T_POINTER: - if (!(expp->nd_symb == '=' || expp->nd_symb == '#')) { - break; - } - /* Fall through */ + if (expp->nd_symb == '=' || + expp->nd_symb == UNEQUAL || + expp->nd_symb == '#') return 1; + break; case T_REAL: return 1; @@ -832,6 +856,7 @@ chk_uoper(expp) break; case NOT: + case '~': if (tpr == bool_type) { if (expp->nd_right->nd_class == Value) { cstunary(expp); diff --git a/lang/m2/comp/cstoper.c b/lang/m2/comp/cstoper.c index be2ba576b..8a671aa09 100644 --- a/lang/m2/comp/cstoper.c +++ b/lang/m2/comp/cstoper.c @@ -38,6 +38,7 @@ cstunary(expp) o1 = -o1; break; case NOT: + case '~': o1 = !o1; break; default: @@ -184,9 +185,11 @@ cstbin(expp) o1 = o1 == o2; break; case '#': + case UNEQUAL: o1 = o1 != o2; break; case AND: + case '&': o1 = o1 && o2; break; case OR: @@ -252,6 +255,7 @@ cstset(expp) case LESSEQUAL: case '=': case '#': + case UNEQUAL: /* Clumsy, but who cares? Nobody writes these things! */ for (j = 0; j < setsize; j++) { switch(expp->nd_symb) { @@ -265,13 +269,14 @@ cstset(expp) continue; case '=': case '#': + case UNEQUAL: if (*set1++ != *set2++) break; continue; } - expp->nd_INT = expp->nd_symb == '#'; + expp->nd_INT = expp->nd_symb != '='; break; } - if (j == setsize) expp->nd_INT = expp->nd_symb != '#'; + if (j == setsize) expp->nd_INT = expp->nd_symb == '='; expp->nd_class = Value; free((char *) expp->nd_left->nd_set); free((char *) expp->nd_right->nd_set); diff --git a/lang/m2/comp/declar.g b/lang/m2/comp/declar.g index e28df724e..b42921fee 100644 --- a/lang/m2/comp/declar.g +++ b/lang/m2/comp/declar.g @@ -7,6 +7,7 @@ static char *RcsId = "$Header$"; #include #include #include + #include "idf.h" #include "LLlex.h" #include "def.h" @@ -18,23 +19,26 @@ static char *RcsId = "$Header$"; int proclevel = 0; /* nesting level of procedures */ extern char *sprint(); +extern struct def *currentdef; } ProcedureDeclaration { struct def *df; + struct def *savecurr = currentdef; } : ProcedureHeading(&df, D_PROCEDURE) { df->prc_level = proclevel++; - + currentdef = df; } ';' block(&(df->prc_body)) IDENT { match_id(dot.TOK_IDF, df->df_idf); df->prc_scope = CurrentScope; - close_scope(SC_CHKFORW); + close_scope(SC_CHKFORW|SC_REVERSE); proclevel--; + currentdef = savecurr; } ; @@ -53,8 +57,14 @@ ProcedureHeading(struct def **pdf; int type;) { tp = construct_type(T_PROCEDURE, tp); tp->prc_params = params; - if (df->df_type && !TstTypeEquiv(tp, df->df_type)) { + if (df->df_type) { + /* We already saw a definition of this type + in the definition module. + */ + if (!TstTypeEquiv(tp, df->df_type)) { error("inconsistent procedure declaration for \"%s\"", df->df_idf->id_text); + } + FreeType(df->df_type); } df->df_type = tp; *pdf = df; @@ -164,7 +174,8 @@ TypeDeclaration }: IDENT { df = define(dot.TOK_IDF, CurrentScope, D_TYPE); } '=' type(&tp) - { df->df_type = tp; + { if (df->df_type) free_type(df->df_type); + df->df_type = tp; if ((df->df_flags&D_EXPORTED) && tp->tp_fund == T_ENUMERATION) { exprt_literals(tp->enm_enums, @@ -327,7 +338,8 @@ FieldList(struct scope *scope; arith *cnt; int *palign;) [ IdentList(&FldList) ':' type(&tp) { *palign = lcm(*palign, tp->tp_align); - EnterIdList(FldList, D_FIELD, 0, tp, scope, cnt); + EnterIdList(FldList, D_FIELD, D_QEXPORTED, + tp, scope, cnt); FreeNode(FldList); } | @@ -373,6 +385,7 @@ FieldList(struct scope *scope; arith *cnt; int *palign;) df->df_type = tp; df->fld_off = align(*cnt, tp->tp_align); *cnt = tcnt = df->fld_off + tp->tp_size; + df->df_flags |= D_QEXPORTED; } OF variant(scope, &tcnt, tp, palign) { max = tcnt; tcnt = *cnt; } diff --git a/lang/m2/comp/def.H b/lang/m2/comp/def.H index 7ae10546a..9810bd298 100644 --- a/lang/m2/comp/def.H +++ b/lang/m2/comp/def.H @@ -53,14 +53,12 @@ struct field { struct dfproc { struct scope *pr_scope; /* scope of procedure */ short pr_level; /* depth level of this procedure */ - char *pr_name; /* name of this procedure */ arith pr_nbpar; /* number of bytes parameters */ struct node *pr_body; /* body of this procedure */ #define prc_scope df_value.df_proc.pr_scope #define prc_level df_value.df_proc.pr_level #define prc_nbpar df_value.df_proc.pr_nbpar #define prc_body df_value.df_proc.pr_body -#define prc_name df_value.df_proc.pr_name }; struct import { diff --git a/lang/m2/comp/def.c b/lang/m2/comp/def.c index c6f49f06e..460e53976 100644 --- a/lang/m2/comp/def.c +++ b/lang/m2/comp/def.c @@ -73,16 +73,6 @@ define(id, scope, kind) (df = lookup(id, PervasiveScope))) ) { switch(df->df_kind) { - case D_PROCHEAD: - if (kind == D_PROCEDURE) { - /* Definition of which the heading was - already seen in a definition module - */ - df->df_kind = kind; - df->prc_name = df->for_name; - return df; - } - break; case D_HIDDEN: if (kind == D_TYPE && !DefinitionModule) { df->df_kind = D_HTYPE; @@ -192,6 +182,7 @@ df->df_idf->id_text); exported from a local module! */ df->df_kind = df1->df_kind; + df->df_value.df_forward = df1->df_value.df_forward; df1->df_kind = D_IMPORT; } df1->imp_def = df; @@ -423,7 +414,10 @@ DeclProc(type) /* C_exp already generated when we saw the definition in the definition module */ - df->df_kind = type; + df->df_kind = D_PROCEDURE; + open_scope(OPENSCOPE); + CurrentScope->sc_name = df->for_name; + df->prc_scope = CurrentScope; } else { df = define(dot.TOK_IDF, CurrentScope, type); @@ -433,12 +427,13 @@ DeclProc(type) } else (sprint(buf, "%s_%s",df->df_scope->sc_name, df->df_idf->id_text)); - df->prc_name = Malloc((unsigned)(strlen(buf)+1)); - strcpy(df->prc_name, buf); + open_scope(OPENSCOPE); + df->prc_scope = CurrentScope; + CurrentScope->sc_name = Malloc((unsigned)(strlen(buf)+1)); + strcpy(CurrentScope->sc_name, buf); C_inp(buf); } df->prc_nbpar = 0; - open_scope(OPENSCOPE); } return df; diff --git a/lang/m2/comp/enter.c b/lang/m2/comp/enter.c index 36e36320e..338b12702 100644 --- a/lang/m2/comp/enter.c +++ b/lang/m2/comp/enter.c @@ -72,6 +72,7 @@ EnterIdList(idlist, kind, flags, type, scope, addr) } else { assert(kind == D_FIELD); + df->fld_off = off; } } @@ -107,6 +108,7 @@ EnterVarList(IdList, type, local) extern char *sprint(), *Malloc(), *strcpy(); scope = CurrentScope; + if (local) { /* Find the closest enclosing open scope. This is the procedure that we are dealing with @@ -127,22 +129,26 @@ node_error(IdList->nd_left,"Illegal type for address"); df->var_off = IdList->nd_left->nd_INT; } else if (local) { - arith off; - - /* add aligned size of variable to the offset + /* subtract aligned size of variable to the offset, + as the variable list exists only local to a + procedure */ - off = scope->sc_off - type->tp_size; - off = -align(-off, type->tp_align); - df->var_off = off; - scope->sc_off = off; + scope->sc_off = -align(type->tp_size - scope->sc_off, + type->tp_align); + df->var_off = scope->sc_off; } else if (!DefinitionModule && CurrentScope != Defined->mod_scope) { + /* variable list belongs to an internal global + module. Align offset and add size + */ scope->sc_off = align(scope->sc_off, type->tp_align); df->var_off = scope->sc_off; scope->sc_off += type->tp_size; } else { + /* Global name, possibly external + */ sprint(buf,"%s_%s", df->df_scope->sc_name, df->df_idf->id_text); df->var_name = Malloc((unsigned)(strlen(buf)+1)); diff --git a/lang/m2/comp/expression.g b/lang/m2/comp/expression.g index 69a750c65..25d070c7c 100644 --- a/lang/m2/comp/expression.g +++ b/lang/m2/comp/expression.g @@ -268,5 +268,5 @@ visible_designator_tail(struct node **pnd;): ]* ']' | - '^' { *pnd = MkNode(Oper, NULLNODE, *pnd, &dot); } + '^' { *pnd = MkNode(Uoper, NULLNODE, *pnd, &dot); } ; diff --git a/lang/m2/comp/main.c b/lang/m2/comp/main.c index cc69c3eaf..0c4532727 100644 --- a/lang/m2/comp/main.c +++ b/lang/m2/comp/main.c @@ -16,6 +16,7 @@ static char *RcsId = "$Header$"; #include "scope.h" #include "standards.h" #include "tokenname.h" +#include "node.h" #include "debug.h" @@ -135,6 +136,7 @@ add_standards() { register struct def *df; struct def *Enter(); + static struct node nilnode = { 0, 0, Value, 0, { INTEGER, 0, 0}}; (void) Enter("ABS", D_PROCEDURE, std_type, S_ABS); (void) Enter("CAP", D_PROCEDURE, std_type, S_CAP); @@ -161,7 +163,11 @@ add_standards() (void) Enter("LONGREAL", D_TYPE, longreal_type, 0); (void) Enter("BOOLEAN", D_TYPE, bool_type, 0); (void) Enter("CARDINAL", D_TYPE, card_type, 0); - (void) Enter("NIL", D_CONST, address_type, 0); + df = Enter("NIL", D_CONST, address_type, 0); + df->con_const = &nilnode; + nilnode.nd_INT = 0; + nilnode.nd_type = address_type; + (void) Enter("PROC", D_TYPE, construct_type(T_PROCEDURE, NULLTYPE), diff --git a/lang/m2/comp/program.g b/lang/m2/comp/program.g index 1e7470840..1d675310f 100644 --- a/lang/m2/comp/program.g +++ b/lang/m2/comp/program.g @@ -22,6 +22,7 @@ static int DEFofIMPL = 0; /* Flag indicating that we are currently implementation module currently being compiled */ +struct def *currentdef; /* current definition of module or procedure */ } /* The grammar as given by Wirth is already almost LL(1); the @@ -46,6 +47,7 @@ ModuleDeclaration { struct idf *id; register struct def *df; + struct def *savecurr = currentdef; extern int proclevel; static int modulecount = 0; char buf[256]; @@ -54,11 +56,14 @@ ModuleDeclaration MODULE IDENT { id = dot.TOK_IDF; df = define(id, CurrentScope, D_MODULE); + currentdef = df; + if (!df->mod_scope) { open_scope(CLOSEDSCOPE); df->mod_scope = CurrentScope; } else CurrentScope = df->mod_scope; + df->df_type = standard_type(T_RECORD, 0, (arith) 0); df->df_type->rec_scope = df->mod_scope; df->mod_number = ++modulecount; @@ -74,8 +79,9 @@ ModuleDeclaration import(1)* export(0)? block(&(df->mod_body)) - IDENT { close_scope(SC_CHKFORW|SC_CHKPROC); + IDENT { close_scope(SC_CHKFORW|SC_CHKPROC|SC_REVERSE); match_id(id, dot.TOK_IDF); + currentdef = savecurr; } ; @@ -198,6 +204,7 @@ definition It is restricted to pointer types. */ { df->df_kind = D_HIDDEN; + df->df_type = construct_type(T_POINTER, NULLTYPE); } ] Semicolon @@ -226,6 +233,7 @@ ProgramModule(int state;) if (state == IMPLEMENTATION) { DEFofIMPL = 1; df = GetDefinitionModule(id); + currentdef = df; CurrentScope = df->mod_scope; DEFofIMPL = 0; } @@ -240,7 +248,7 @@ ProgramModule(int state;) priority(&(df->mod_priority))? ';' import(0)* block(&(df->mod_body)) IDENT - { close_scope(SC_CHKFORW|SC_CHKPROC); + { close_scope(SC_CHKFORW|SC_CHKPROC|SC_REVERSE); match_id(id, dot.TOK_IDF); } '.' diff --git a/lang/m2/comp/scope.C b/lang/m2/comp/scope.C index 4a448c7ec..9aad947ad 100644 --- a/lang/m2/comp/scope.C +++ b/lang/m2/comp/scope.C @@ -6,12 +6,14 @@ static char *RcsId = "$Header$"; #include #include #include + #include "LLlex.h" #include "idf.h" #include "scope.h" #include "type.h" #include "def.h" #include "node.h" + #include "debug.h" struct scope *CurrentScope, *PervasiveScope, *GlobalScope; @@ -212,7 +214,7 @@ close_scope(flag) DO_DEBUG(2, PrScopeDef(sc->sc_def)); if (flag & SC_CHKPROC) chk_proc(sc->sc_def); if (flag & SC_CHKFORW) chk_forw(&(sc->sc_def)); - Reverse(&(sc->sc_def)); + if (flag & SC_REVERSE) Reverse(&(sc->sc_def)); } CurrentScope = sc->next; scp_level = CurrentScope->sc_level; diff --git a/lang/m2/comp/scope.h b/lang/m2/comp/scope.h index e2611f3da..adddeef58 100644 --- a/lang/m2/comp/scope.h +++ b/lang/m2/comp/scope.h @@ -11,6 +11,9 @@ #define SC_CHKPROC 2 /* Check for forward procedure definitions when closing a scope */ +#define SC_REVERSE 4 /* Reverse list of definitions, to get it + back into original order + */ struct scope { struct scope *next; diff --git a/lang/m2/comp/statement.g b/lang/m2/comp/statement.g index c30e66b31..b80c8cb38 100644 --- a/lang/m2/comp/statement.g +++ b/lang/m2/comp/statement.g @@ -5,11 +5,15 @@ static char *RcsId = "$Header$"; #include #include +#include "idf.h" #include "LLlex.h" +#include "scope.h" +#include "def.h" #include "type.h" #include "node.h" static int loopcount = 0; /* Count nested loops */ +extern struct def *currentdef; } statement(struct node **pnd;) @@ -55,7 +59,7 @@ statement(struct node **pnd;) | EXIT { if (!loopcount) { - error("EXIT not in a LOOP"); +error("EXIT not in a LOOP"); } *pnd = MkNode(Stat, NULLNODE, NULLNODE, &dot); } @@ -63,6 +67,13 @@ statement(struct node **pnd;) RETURN { *pnd = nd = MkNode(Stat, NULLNODE, NULLNODE, &dot); } [ expression(&(nd->nd_right)) + { if (scopeclosed(CurrentScope)) { +error("a module body has no result value"); + } + else if (! currentdef->df_type->next) { +error("procedure \"%s\" has no result value", currentdef->df_idf->id_text); + } + } ]? ]? ; diff --git a/lang/m2/comp/type.c b/lang/m2/comp/type.c index 21e4bb594..1cc5cfbf7 100644 --- a/lang/m2/comp/type.c +++ b/lang/m2/comp/type.c @@ -9,6 +9,7 @@ static char *RcsId = "$Header$"; #include "target_sizes.h" #include "debug.h" +#include "maxset.h" #include "def.h" #include "type.h" @@ -131,28 +132,61 @@ standard_type(fund, align, size) init_types() { + /* Initialize the predefined types + */ register struct type *tp; + /* character type + */ char_type = standard_type(T_CHAR, 1, (arith) 1); char_type->enm_ncst = 256; + + /* character constant, different from char because of compatibility + with ARRAY OF CHAR + */ charc_type = standard_type(T_CHAR, 1, (arith) 1); charc_type->enm_ncst = 256; + + /* boolean type + */ bool_type = standard_type(T_ENUMERATION, 1, (arith) 1); bool_type->enm_ncst = 2; + + /* integer types, also a "intorcard", for integer constants between + 0 and MAX(INTEGER) + */ int_type = standard_type(T_INTEGER, int_align, int_size); longint_type = standard_type(T_INTEGER, long_align, long_size); card_type = standard_type(T_CARDINAL, int_align, int_size); + intorcard_type = standard_type(T_INTORCARD, int_align, int_size); + + /* floating types + */ real_type = standard_type(T_REAL, float_align, float_size); longreal_type = standard_type(T_REAL, double_align, double_size); - word_type = standard_type(T_WORD, word_align, word_size); - intorcard_type = standard_type(T_INTORCARD, int_align, int_size); + + /* string constant type + */ string_type = standard_type(T_STRING, 1, (arith) -1); + + /* SYSTEM types + */ + word_type = standard_type(T_WORD, word_align, word_size); address_type = construct_type(T_POINTER, word_type); + + /* create BITSET type + */ tp = construct_type(T_SUBRANGE, int_type); tp->sub_lb = 0; tp->sub_ub = word_size * 8 - 1; bitset_type = set_type(tp); + + /* a unique type for standard procedures and functions + */ std_type = construct_type(T_PROCEDURE, NULLTYPE); + + /* a unique type indicating an error + */ error_type = standard_type(T_CHAR, 1, (arith) 1); } @@ -183,11 +217,12 @@ ParamList(ids, tp, VARp) return pstart; } -/* A subrange had a specified base. Check that the bases conform ... -*/ chk_basesubrange(tp, base) register struct type *tp, *base; { + /* A subrange had a specified base. Check that the bases conform. + */ + if (base->tp_fund == T_SUBRANGE) { /* Check that the bounds of "tp" fall within the range of "base" @@ -197,6 +232,7 @@ chk_basesubrange(tp, base) } base = base->next; } + if (base->tp_fund == T_ENUMERATION || base->tp_fund == T_CHAR) { if (tp->next != base) { error("Specified base does not conform"); @@ -212,6 +248,7 @@ chk_basesubrange(tp, base) else if (base != tp->next && base != int_type) { error("Specified base does not conform"); } + tp->next = base; tp->tp_size = base->tp_size; tp->tp_align = base->tp_align; @@ -233,14 +270,18 @@ subr_type(lb, ub) } if (tp->tp_fund == T_SUBRANGE) tp = tp->next; - if (tp == intorcard_type) tp = card_type; /* lower bound > 0 */ + + if (tp == intorcard_type) { + /* Lower bound >= 0; in this case, the base type is CARDINAL, + according to the language definition, par. 6.3 + */ + assert(lb->nd_INT >= 0); + tp = card_type; + } /* Check base type */ - if (tp != int_type && tp != card_type && tp != char_type && - tp->tp_fund != T_ENUMERATION) { - /* BOOLEAN is also an ENUMERATION type - */ + if (! (tp->tp_fund & T_DISCRETE)) { node_error(ub, "Illegal base type for subrange"); return error_type; } @@ -258,10 +299,8 @@ subr_type(lb, ub) res->sub_ub = ub->nd_INT; res->tp_size = tp->tp_size; res->tp_align = tp->tp_align; - DO_DEBUG(2,debug("Creating subrange type %ld-%ld", (long)lb->nd_INT,(long)ub->nd_INT)); return res; } -#define MAX_SET 1024 /* ??? Maximum number of elements in a set */ struct type * set_type(tp) @@ -273,14 +312,14 @@ set_type(tp) arith lb, ub; if (tp->tp_fund == T_SUBRANGE) { - if ((lb = tp->sub_lb) < 0 || (ub = tp->sub_ub) > MAX_SET - 1) { + if ((lb = tp->sub_lb) < 0 || (ub = tp->sub_ub) > MAXSET - 1) { error("Set type limits exceeded"); return error_type; } } else if (tp->tp_fund == T_ENUMERATION || tp == char_type) { lb = 0; - if ((ub = tp->enm_ncst - 1) > MAX_SET - 1) { + if ((ub = tp->enm_ncst - 1) > MAXSET - 1) { error("Set type limits exceeded"); return error_type; } @@ -289,6 +328,7 @@ set_type(tp) error("illegal base type for set"); return error_type; } + tp = construct_type(T_SET, tp); tp->tp_size = align(((ub - lb) + 7)/8, word_align); return tp; @@ -297,40 +337,68 @@ set_type(tp) ArraySizes(tp) register struct type *tp; { - /* Assign sizes to an array type + /* Assign sizes to an array type, and check index type */ arith elem_size; - register struct type *itype = tp->next; /* the index type */ + register struct type *index_type = tp->next; + register struct type *elem_type = tp->arr_elem; - if (tp->arr_elem->tp_fund == T_ARRAY) { - ArraySizes(tp->arr_elem); + if (elem_type->tp_fund == T_ARRAY) { + ArraySizes(elem_type); } - elem_size = align(tp->arr_elem->tp_size, tp->arr_elem->tp_align); - tp->tp_align = tp->arr_elem->tp_align; + /* align element size to alignment requirement of element type + */ + elem_size = align(elem_type->tp_size, elem_type->tp_align); + tp->tp_align = elem_type->tp_align; - if (! (itype->tp_fund & T_INDEX)) { + /* check index type + */ + if (! (index_type->tp_fund & T_INDEX)) { error("Illegal index type"); tp->tp_size = 0; return; } - switch(itype->tp_fund) { + /* find out HIGH, LOW and size of ARRAY + */ + switch(index_type->tp_fund) { case T_SUBRANGE: - tp->arr_lb = itype->sub_lb; - tp->arr_ub = itype->sub_ub; - tp->tp_size = elem_size * (itype->sub_ub - itype->sub_lb + 1); + tp->arr_lb = index_type->sub_lb; + tp->arr_ub = index_type->sub_ub; + tp->tp_size = elem_size * + (index_type->sub_ub - index_type->sub_lb + 1); break; case T_CHAR: case T_ENUMERATION: tp->arr_lb = 0; - tp->arr_ub = itype->enm_ncst - 1; - tp->tp_size = elem_size * itype->enm_ncst; + tp->arr_ub = index_type->enm_ncst - 1; + tp->tp_size = elem_size * index_type->enm_ncst; break; default: assert(0); } - /* ??? overflow checking ??? */ + /* ??? overflow checking ??? + */ +} + +FreeType(tp) + struct type *tp; +{ + /* Release type structures indicated by "tp" + */ + register struct paramlist *pr, *pr1; + + assert(tp->tp_fund == T_PROCEDURE); + + pr = tp->prc_params; + while (pr) { + pr1 = pr; + pr = pr->next; + free_paramlist(pr1); + } + + free_type(tp); } int diff --git a/lang/m2/comp/typequiv.c b/lang/m2/comp/typequiv.c index 603d35fe2..3054afc35 100644 --- a/lang/m2/comp/typequiv.c +++ b/lang/m2/comp/typequiv.c @@ -12,21 +12,31 @@ static char *RcsId = "$Header$"; int TstTypeEquiv(tp1, tp2) - register struct type *tp1, *tp2; + struct type *tp1, *tp2; { - /* test if two types are equivalent. A complication comes - from the fact that for some procedures two declarations may - be given: one in the specification module and one in the - definition module. - A related problem is that two dynamic arrays with - equivalent base types are also equivalent. + /* test if two types are equivalent. */ return tp1 == tp2 || tp1 == error_type || - tp2 == error_type + tp2 == error_type; +} + +int +TstParEquiv(tp1, tp2) + register struct type *tp1, *tp2; +{ + /* test if two parameter types are equivalent. This routine + is used to check if two different procedure declarations + (one in the definition module, one in the implementation + module) are equivalent. A complication comes from dynamic + arrays. + */ + + return + TstTypeEquiv(tp1, tp2) || ( tp1->tp_fund == T_ARRAY @@ -38,16 +48,7 @@ TstTypeEquiv(tp1, tp2) tp2->next == 0 && TstTypeEquiv(tp1->arr_elem, tp2->arr_elem) - ) - || - ( - tp1 && tp1->tp_fund == T_PROCEDURE - && - tp2 && tp2->tp_fund == T_PROCEDURE - && - TstProcEquiv(tp1, tp2) ); - } int @@ -61,14 +62,17 @@ TstProcEquiv(tp1, tp2) register struct paramlist *p1, *p2; if (!TstTypeEquiv(tp1->next, tp2->next)) return 0; + p1 = tp1->prc_params; p2 = tp2->prc_params; + while (p1 && p2) { if (p1->par_var != p2->par_var || - !TstTypeEquiv(p1->par_type, p2->par_type)) return 0; + !TstParEquiv(p1->par_type, p2->par_type)) return 0; p1 = p1->next; p2 = p2->next; } + return p1 == p2; } @@ -79,9 +83,12 @@ TstCompat(tp1, tp2) /* test if two types are compatible. See section 6.3 of the Modula-2 Report for a definition of "compatible". */ + if (TstTypeEquiv(tp1, tp2)) return 1; + if (tp1->tp_fund == T_SUBRANGE) tp1 = tp1->next; if (tp2->tp_fund == T_SUBRANGE) tp2 = tp2->next; + return tp1 == tp2 || ( tp1 == intorcard_type @@ -117,12 +124,15 @@ int TstAssCompat(tp1, tp2) { /* Test if two types are assignment compatible. */ + if (TstCompat(tp1, tp2)) return 1; if (tp1->tp_fund == T_SUBRANGE) tp1 = tp1->next; if (tp2->tp_fund == T_SUBRANGE) tp2 = tp2->next; - if ((tp1->tp_fund & (T_INTEGER|T_CARDINAL)) && - (tp2->tp_fund & (T_INTEGER|T_CARDINAL))) return 1; + + if ((tp1->tp_fund & T_INTORCARD) && + (tp2->tp_fund & T_INTORCARD)) return 1; + if (tp1 == char_type && tp2 == charc_type) return 1; if (tp1->tp_fund == T_ARRAY && (tp2 == charc_type || tp2 == string_type)) { @@ -133,5 +143,6 @@ int TstAssCompat(tp1, tp2) if (tp1->tp_fund == T_SUBRANGE) tp1 = tp1->next; return tp1 == char_type; } + return 0; } diff --git a/lang/m2/comp/walk.c b/lang/m2/comp/walk.c index d23bbdf0e..653b6db6f 100644 --- a/lang/m2/comp/walk.c +++ b/lang/m2/comp/walk.c @@ -16,11 +16,14 @@ static char *RcsId = "$Header$"; #include "main.h" #include "LLlex.h" #include "node.h" +#include "Lpars.h" #include "debug.h" extern arith align(); static int prclev = 0; +static label instructionlabel = 0; +static label datalabel = 0; WalkModule(module) register struct def *module; @@ -33,10 +36,12 @@ WalkModule(module) scope = CurrentScope; CurrentScope = module->mod_scope; + if (!prclev && module->mod_number) { /* This module is a local module, but not within a procedure. Generate code to allocate storage for its - variables + variables. This is done by generating a "bss", + with label "_". */ arith size = align(CurrentScope->sc_off, word_size); @@ -69,7 +74,7 @@ WalkModule(module) CurrentScope->sc_off = 0; C_pro_narg(CurrentScope->sc_name); MkCalls(CurrentScope->sc_def); - WalkNode(module->mod_body); + WalkNode(module->mod_body, (label) 0); C_end(align(-CurrentScope->sc_off, word_size)); CurrentScope = scope; @@ -91,12 +96,13 @@ WalkProcedure(procedure) /* Generate code for this procedure */ - C_pro_narg(procedure->prc_name); + C_pro_narg(CurrentScope->sc_name); /* generate calls to initialization routines of modules defined within this procedure */ + instructionlabel = 1; MkCalls(CurrentScope->sc_def); - WalkNode(procedure->prc_body); + WalkNode(procedure->prc_body, (label) 0); C_end(align(-CurrentScope->sc_off, word_size)); CurrentScope = scope; prclev--; @@ -126,17 +132,151 @@ MkCalls(df) while (df) { if (df->df_kind == D_MODULE) { C_lxl((arith) 0); - C_cal(df->df_scope->sc_name); + C_cal(df->mod_scope->sc_name); } df = df->df_nextinscope; } } -WalkNode(nd) - struct node *nd; +WalkNode(nd, lab) + register struct node *nd; + label lab; { /* Node "nd" represents either a statement or a statement list. - Generate code for it. + Walk through it. + "lab" represents the label that must be jumped to on + encountering an EXIT statement. + */ + + while (nd->nd_class == Link) { /* statement list */ + WalkStat(nd->nd_left, lab); + nd = nd->nd_right; + } + + WalkStat(nd, lab); +} + +WalkStat(nd, lab) + register struct node *nd; + label lab; +{ + /* Walk through a statement, generating code for it. + "lab" represents the label that must be jumped to on + encountering an EXIT statement. + */ + register struct node *left = nd->nd_left; + register struct node *right = nd->nd_right; + + if (nd->nd_class == Call) { + /* ??? */ + return; + } + + assert(nd->nd_class == Stat); + + switch(nd->nd_symb) { + case BECOMES: + /* ??? */ + break; + + case IF: + { label l1, l2; + + l1 = instructionlabel++; + l2 = instructionlabel++; + ExpectBool(left); + assert(right->nd_symb == THEN); + C_zeq(l1); + WalkNode(right->nd_left, lab); + + if (right->nd_right) { /* ELSE part */ + C_bra(l2); + C_df_ilb(l1); + WalkNode(right->nd_right, lab); + C_df_ilb(l2); + } + else C_df_ilb(l1); + break; + } + + case CASE: + /* ??? */ + break; + + case WHILE: + { label l1, l2; + + l1 = instructionlabel++; + l2 = instructionlabel++; + C_df_ilb(l1); + ExpectBool(left); + C_zeq(l2); + WalkNode(right, lab); + C_bra(l1); + C_df_ilb(l2); + break; + } + + case REPEAT: + { label l1; + + l1 = instructionlabel++; + C_df_ilb(l1); + WalkNode(left, lab); + ExpectBool(right); + C_zeq(l1); + break; + } + + case LOOP: + { label l1, l2; + + l1 = instructionlabel++; + l2 = instructionlabel++; + C_df_ilb(l1); + WalkNode(left, l2); + C_bra(l1); + C_df_ilb(l2); + break; + } + + case FOR: + /* ??? */ + break; + + case WITH: + /* ??? */ + break; + + case EXIT: + assert(lab != 0); + + C_bra(lab); + break; + + case RETURN: + /* ??? */ + break; + + default: + assert(0); + } +} + +ExpectBool(nd) + struct node *nd; +{ + /* "nd" must indicate a boolean expression. Check this and + generate code to evaluate the expression. + */ + + chk_expr(nd); + + if (nd->nd_type != bool_type) { + node_error(nd, "boolean expression expected"); + } + + /* generate code */ /* ??? */ }