/[ascend]/trunk/ascend/compiler/typelint.c
ViewVC logotype

Contents of /trunk/ascend/compiler/typelint.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2587 - (show annotations) (download) (as text)
Tue Apr 10 20:27:46 2012 UTC (10 years, 2 months ago) by jpye
File MIME type: text/x-csrc
File size: 29165 byte(s)
minor formatting, one small 'case' error.
1 /*
2 * Type definition lint module
3 * by Ben Allan
4 * Created: 9/16/96
5 * Version: $Revision: 1.48 $
6 * Version control file: $RCSfile: typelint.c,v $
7 * Date last modified: $Date: 1998/07/23 13:57:59 $
8 * Last modified by: $Author: ballan $
9 *
10 * This file is part of the Ascend Language Interpreter.
11 *
12 * Copyright (C) 1996 Benjamin Andrew Allan
13 *
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2, or (at your option)
17 any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA.
28 */
29
30 #include <math.h>
31 #include <ctype.h>
32 #include <ascend/general/platform.h>
33 #include <ascend/general/list.h>
34 #include <ascend/general/dstring.h>
35
36 #include "functype.h"
37 #include "expr_types.h"
38 #include "stattypes.h"
39 #include "statement.h"
40 #include "slist.h"
41 #include "statio.h"
42 #include "symtab.h"
43 #include "module.h"
44 #include "library.h"
45 #include "child.h"
46 #include "vlist.h"
47 #include "vlistio.h"
48 #include "name.h"
49 #include "nameio.h"
50 #include "when.h"
51 #include "select.h"
52 #include "switch.h"
53 #include "sets.h"
54 #include "exprs.h"
55 #include "forvars.h"
56 #include "syntax.h"
57 #include "setinstval.h"
58 #include "childinfo.h"
59 #include "evaluate.h"
60 #include "proc.h"
61 #include "type_desc.h"
62 #include "typedef.h"
63 #include "typelint.h"
64
65 struct errormessage {
66 const char *str;
67 int level;
68 };
69
70 /*
71 * Messages with a level < g_parser_warnings do not get printed.
72 * g_parser_warnings ==
73 * 2 => suppress style warnings.
74 * 3 => suppress warnings
75 * 4 => suppress errors
76 * 5 => suppress fatality explanations.
77 * The effect is obviously cumulative.
78 */
79 int g_parser_warnings = 0;
80
81 static struct errormessage g_DefinitionErrorMessages[] = {
82 /*0*/{"No error",0},
83 {"Name of a part has been reused (failure)",3},
84 {"Name of a part has incorrect structure (failure)",3},
85 {"Name of a part/variable that does not exist",3},
86 {"Name of undefined function (failure)",3},
87 /*5*/{"Illegal right hand side type in ALIASES",3},
88 {"Illegal expression encountered (parser, lint or memory error, failure)",3},
89 {"Illegal parameter type for WILL_BE (failure)",3},
90 {"Statement not allowed in context (failure)",3},
91 {"Illegal parameter (more than 1 name per IS_A/WILL_BE - failure)",3},
92 /*10*/{"Illegal parameter reduction (LHS not defined by ancestral IS_A)",3},
93 {"Illegal parameter reduction (reassigning part - failure)",3},
94 {"Illegal parameter type for IS_A (punting). Try WILL_BE?",3},
95 {"Unverifiable name or illegal type in a relation",2},
96 {"Unverifiable name or illegal type in RHS of :==",2},
97 /*15*/{"Incorrect number of arguments passed to parameterized type. (failure)",3},
98 {"Incorrect argument passed to parameterized type. (failure)",3},
99 {"Statement possibly modifies type of parameter. (failure)",3},
100 {"Unverifiable LHS of :==, possibly undefined part or non-constant type",2},
101 {"Unverifiable LHS of :=, possibly undefined part or non-variable type",2},
102 /*20*/{"Illegal type or undefined name in RHS of := (failure)",3},
103 {"Object with incompatible type specified in refinement",3},
104 {"FOR loop index shadows previous declaration (failure)",3},
105 {"Unverifiable name or illegal type in ARE_ALIKE",2},
106 {"Illegal parameterized type in ARE_ALIKE",3},
107 /*25*/{"Illegal set of array elements in ARE_ALIKE",3},
108 {"WILL(_NOT)_BE_THE_SAME contains incorrect names.",3},
109 {"WILL_BE in WHERE clause not yet implemented.",3},
110 {"Mismatched alias array subscript and set name in ALIASES-ISA.",3},
111 {"Unverifiable FOR loop set, possibly undefined part or non-constant type", 2},
112 /*30*/{"SELECT statements are not allowed inside a FOR loop",3},
113 {"Illegal relation -- too many relational operators (<,>,=,<=,>=,<>)",3},
114 {"Illegal logical relation -- too many equality operators (!=,==)",3},
115 {"Illegal USE found outside WHEN statement",3},
116 {"Illegal FOR used in a method must be FOR/DO",3},
117 /*35*/{"Illegal FOR used in body must be FOR/CREATE",3},
118 {"Illegal ATOM attribute or relation type in ARE_THE_SAME",3},
119 {":= used outside METHOD makes models hard to debug or reuse",1},
120 {"Illegal BREAK used outside loop or SWITCH.",3},
121 {"Illegal CONTINUE used outside loop.",3},
122 /*40*/{"Illegal FALL_THROUGH used outside SWITCH.",3},
123 {"Incorrect nested argument definition for MODEL. (failure)",3},
124 {"Indexed relation has incorrect subscripts. (failure)",3},
125 {"Illegal FOR used in WHERE statements must be FOR/CHECK",3},
126 {"Illegal FOR used in parameter definitions must be FOR/EXPECT",3},
127 /*45*/{"Miscellaneous style",1},
128 {"Miscellaneous warning",2},
129 {"Miscellaneous error",3},
130 {"Unknown error encountered in statement",5}
131 };
132
133 void TypeLintErrorAuxillary(FILE *f, char *str, enum typelinterr err,
134 int uselabel)
135 {
136 assert(f!=NULL);
137 assert(str!=NULL);
138 if (g_DefinitionErrorMessages[err].level < g_parser_warnings) {
139 /* no element of gDEM should have .level == 0 */
140 return;
141 }
142 if (uselabel) {
143 FPRINTF(f,"%s%s",StatioLabel(g_DefinitionErrorMessages[err].level),str);
144 } else {
145 FPRINTF(f,"%s",str);
146 }
147 }
148
149 void TypeLintError(FILE *f, CONST struct Statement *stat,enum typelinterr err)
150 {
151 assert(f!=NULL);
152 assert(stat!=NULL);
153 if (g_DefinitionErrorMessages[err].level < g_parser_warnings) {
154 /* no element of gDEM should have .level == 0 */
155 return;
156 }
157 WSSM(f,stat,g_DefinitionErrorMessages[err].str,
158 g_DefinitionErrorMessages[err].level);
159 }
160
161 void TypeLintName(FILE *f, CONST struct Name *n, char *m)
162 {
163 TypeLintNameMsg(f,n,m,0);
164 }
165
166 void TypeLintNameMsg(FILE *f, CONST struct Name *n, char *m,int level)
167 {
168 assert(f!=NULL);
169 assert(n!=NULL);
170 assert(m!=NULL);
171 if (level > 0 && level < g_parser_warnings) {
172 return;
173 }
174 switch(level){
175 case 2:
176 ERROR_REPORTER_START_NOLINE(ASC_PROG_WARNING);
177 break;
178 case 3:
179 ERROR_REPORTER_START_NOLINE(ASC_PROG_ERROR);
180 break;
181 case 4:
182 ERROR_REPORTER_START_NOLINE(ASC_PROG_FATAL);
183 break;
184 default:
185 ERROR_REPORTER_START_NOLINE(ASC_PROG_NOTE);
186 }
187 FPRINTF(f,"%s",m);
188 WriteName(f,n);
189 error_reporter_end_flush();
190 }
191
192 void TypeLintNameNode(FILE *f, CONST struct Name *n, char *m)
193 {
194 assert(f!=NULL);
195 assert(n!=NULL);
196 assert(m!=NULL);
197 FPRINTF(f,"%s",m);
198 WriteNameNode(f,n);
199 FPRINTF(f,"\n");
200 }
201
202 void TypeLintNameNodeMsg(FILE*f, CONST struct Name *n, char *m)
203 {
204 assert(f!=NULL);
205 assert(n!=NULL);
206 assert(m!=NULL);
207 if (3 < g_parser_warnings) {
208 return;
209 }
210 ERROR_REPORTER_START_NOLINE(ASC_USER_ERROR);
211 FPRINTF(f,"%s '",m);
212 WriteNameNode(f,n);
213 FPRINTF(f,"'");
214 error_reporter_end_flush();
215 }
216
217 /*
218 * Returns position of first compound name in list
219 * if a CompoundName (e.g. a.b) is found in the
220 * list. Array names are simple e.g. a[i][j],
221 * but compound names include names like a[i][j].b.
222 * Returns -1 OTHERWISE.
223 */
224 static
225 int CompoundNameInList(CONST struct VariableList *vl)
226 {
227 int rval = 0;
228 while (vl != NULL) {
229 if (NameCompound(NamePointer(vl))) {
230 return rval;
231 }
232 vl = NextVariableNode(vl);
233 rval++;
234 }
235 return -1;
236 }
237
238 /*
239 * pulls the single name element out of the last set name (subscript)
240 * in the alias array name of the ALIASES-IS_A statement.
241 */
242 static
243 CONST struct Name *ExtractARRName(CONST struct Statement *s)
244 {
245 CONST struct Name *n;
246 CONST struct Set *sn;
247 CONST struct Expr *ex;
248 int len;
249
250 assert(s!=NULL);
251 assert(StatementType(s)==ARR);
252
253 /* get name from var. */
254 n = NamePointer(ArrayStatAvlNames(s));
255 len = NameLength(n);
256 if (len < 2) {
257 return NULL;
258 }
259 /* get last subscript in name */
260 while (len > 1) {
261 len--;
262 n = NextName(n);
263 }
264 /* must be subscript */
265 if (NameId(n)!=0) {
266 return NULL;
267 }
268 sn = NameSetPtr(n);
269 /* must be single set, not range */
270 if (SetType(sn)!=0) {
271 return NULL;
272 }
273 ex = GetSingleExpr(sn);
274 /* must be name of var we're to IS_A elsewhere */
275 if (ExprListLength(ex) != 1 || ExprType(ex) !=e_var) {
276 return NULL;
277 }
278 return ExprName(ex);
279 }
280
281 static int g_tlibs_depth=0;
282 /* counter to avoid redundant spew */
283 enum typelinterr TypeLintIllegalBodyStats(FILE *fp,
284 symchar *name,
285 CONST struct StatementList *sl,
286 unsigned int context)
287 {
288 unsigned long c,len;
289 struct gl_list_t *gl;
290 struct Statement *s;
291 struct TypeDescription *d;
292 enum typelinterr rval = DEF_OKAY, tmperr;
293 struct SelectList *selcase;
294 struct WhenList *wcase;
295 struct StatementList *slint;
296
297 g_tlibs_depth++;
298 assert(name !=NULL);
299 len = StatementListLength(sl);
300 if (len == 0L) {
301 g_tlibs_depth--;
302 return rval;
303 }
304 gl = GetList(sl);
305 for(c=1; c<=len; c++) {
306 s = (struct Statement *)gl_fetch(gl,c);
307 switch(StatementType(s)) {
308 case ISA:
309 d = FindType(GetStatType(s));
310 if (GetBaseType(d)== model_type || GetBaseType(d) == patch_type) {
311 /* check arg list length. can't do types until after. */
312 if (GetModelParameterCount(d) != SetLength(GetStatTypeArgs(s))) {
313 if (TLINT_ERROR) {
314 FPRINTF(fp,"%sType %s needs %u arguments. Got %lu.\n",
315 StatioLabel(3),
316 SCP(GetStatType(s)),
317 GetModelParameterCount(d),
318 SetLength(GetStatTypeArgs(s)));
319 }
320 rval = DEF_ARGNUM_INCORRECT;
321 TypeLintError(fp,s,rval);
322 break;
323 }
324 }
325 /* fall through */
326 case ALIASES:
327 /* check simple name */
328 if (CompoundNameInList(GetStatVarList(s)) != -1) {
329 if (TLINT_ERROR) {
330 FPRINTF(fp,
331 "%sCannot create parts in another object with IS_A/ALIASES.\n",
332 StatioLabel(3));
333 FPRINTF(fp,"%sName %d is incorrect.\n",
334 StatioLabel(3),
335 CompoundNameInList(GetStatVarList(s)));
336 }
337 rval = DEF_NAME_INCORRECT;
338 TypeLintError(fp,s,rval);
339 }
340 break;
341 case ARR:
342 /* like ALIASES, only different. */
343 /* assumptions about the parser: the avlname and setname varlists
344 * will only have 1 name pointer in them, as the parser stops
345 * longer lists.
346 */
347 /* check simple names */
348 if (CompoundNameInList(ArrayStatAvlNames(s)) != -1) {
349 if (TLINT_ERROR) {
350 FPRINTF(fp,"%sCannot create parts in another object with ALIASES.\n",
351 StatioLabel(3));
352 }
353 rval = DEF_NAME_INCORRECT;
354 TypeLintError(fp,s,rval);
355 }
356 if (CompoundNameInList(ArrayStatSetName(s)) != -1) {
357 if (TLINT_ERROR) {
358 FPRINTF(fp,"%sCannot create parts in another object with IS_A.\n",
359 StatioLabel(3));
360 }
361 rval = DEF_NAME_INCORRECT;
362 TypeLintError(fp,s,rval);
363 }
364 if (CompareNames(NamePointer(ArrayStatSetName(s)),ExtractARRName(s))) {
365 if (TLINT_ERROR) {
366 FPRINTF(fp,"%sName of set defined with IS_A ",StatioLabel(3));
367 WriteVariableList(fp,ArrayStatSetName(s));
368 FPRINTF(fp,"\n must match last subscript of ALIASES-ISA LHS.\n");
369 }
370 rval = DEF_ARR_INCORRECT;
371 TypeLintError(fp,s,rval);
372 }
373 break;
374 case REL:
375 /* check simple name */
376 if (NameCompound(RelationStatName(s)) != 0) {
377 if (TLINT_ERROR) {
378 FPRINTF(fp,"%sCannot create relations in another object.\n",
379 StatioLabel(3));
380 }
381 rval = DEF_NAME_INCORRECT;
382 TypeLintError(fp,s,rval);
383 }
384 if (NumberOfRelOps(RelationStatExpr(s)) > 1) {
385 rval = DEF_TOOMANY_RELOP;
386 TypeLintError(fp,s,rval);
387 }
388 break;
389 case LOGREL:
390 /* check simple name */
391 if (NameCompound(LogicalRelStatName(s)) != 0) {
392 if (TLINT_ERROR) {
393 FPRINTF(fp,"%sCannot create logical relations in another object.\n",
394 StatioLabel(3));
395 }
396 rval = DEF_NAME_INCORRECT;
397 TypeLintError(fp,s,rval);
398 }
399 if (NumberOfRelOps(LogicalRelStatExpr(s)) > 1) {
400 rval = DEF_TOOMANY_LOGOP;
401 TypeLintError(fp,s,rval);
402 }
403 break;
404 case IRT:
405 d = FindType(GetStatType(s));
406 if (GetBaseType(d)== model_type || GetBaseType(d) == patch_type) {
407 /* check arg list length. can't do types until after. */
408 if (GetModelParameterCount(d) != SetLength(GetStatTypeArgs(s))) {
409 if (TLINT_ERROR) {
410 FPRINTF(fp,"%sType %s needs %u arguments. Got %lu.\n",
411 StatioLabel(3),
412 SCP(GetStatType(s)),
413 GetModelParameterCount(d),
414 SetLength(GetStatTypeArgs(s)));
415 }
416 rval = DEF_ARGNUM_INCORRECT;
417 TypeLintError(fp,s,rval);
418 break;
419 }
420 }
421 break;
422 case ATS:
423 break;
424 case AA:
425 if(TLINT_STYLE){
426 FPRINTF(fp,"%sType \"%s\" contains AA:\n",
427 StatioLabel(1),SCP(name));
428 WriteStatement(fp,s,2);
429 }
430 break;
431 case LNK:
432 if(TLINT_STYLE){
433 FPRINTF(fp,"%sType \"%s\" contains LNK:\n",
434 StatioLabel(1),SCP(name));
435 WriteStatement(fp,s,2);
436 }
437 break;
438 case UNLNK:
439 if(TLINT_STYLE){
440 FPRINTF(fp,"%sType \"%s\" contains UNLNK:\n",
441 StatioLabel(1),SCP(name));
442 WriteStatement(fp,s,2);
443 }
444 break;
445 case FOR:
446 if (ForContainsSelect(s)) {
447 rval = DEF_ILLEGAL_SELECT;
448 TypeLintError(fp,s,rval);
449 }
450 if (ForLoopKind(s) != fk_create) {
451 rval = DEF_FOR_NOTBODY; /* err fatal to type */
452 TypeLintError(fp,s,rval);
453 } else {
454 tmperr = TypeLintIllegalBodyStats(fp,name,ForStatStmts(s),
455 (context | context_FOR));
456 if (tmperr != DEF_OKAY) {
457 /* don't want DEF_OKAY to wipe out rval if badness already found.
458 */
459 rval = tmperr;
460 }
461 }
462 break;
463 case ASGN:
464 TypeLintError(fp,s,DEF_STAT_BODYASGN);
465 TypeLintErrorAuxillary(fp,
466 " Move default assignments to METHOD default_self.\n",
467 DEF_STAT_BODYASGN,FALSE);
468 break;
469 case CASGN:
470 break;
471 case FNAME:
472 if ((context & context_WHEN) == 0) {
473 rval = DEF_USE_NOTWHEN;
474 TypeLintError(fp,s,rval);
475 if ((context & context_SELECT) != 0) {
476 FPRINTF(fp," Perhaps the surrounding SELECT should be WHEN?\n");
477 }
478 }
479 break;
480 case WHEN:
481 /* check simple name */
482 /* vicente, what's up with this? we can name whens? */
483 if (NameCompound(WhenStatName(s)) != 0) {
484 FPRINTF(fp," Cannot create whens in another object.\n");
485 rval = DEF_NAME_INCORRECT;
486 TypeLintError(fp,s,rval);
487 }
488 wcase = WhenStatCases(s);
489 while ( wcase!=NULL ) {
490 slint = WhenStatementList(wcase);
491 tmperr = TypeLintIllegalBodyStats(fp,name,slint,
492 (context | context_WHEN));
493 if (tmperr != DEF_OKAY) {
494 rval = tmperr;
495 }
496 wcase = NextWhenCase(wcase);
497 }
498 break;
499 case SELECT:
500 selcase = SelectStatCases(s);
501 while ( selcase!=NULL ) {
502 slint = SelectStatementList(selcase);
503 tmperr = TypeLintIllegalBodyStats(fp,name,slint,
504 (context | context_SELECT));
505 if (tmperr != DEF_OKAY) {
506 rval = tmperr;
507 }
508 selcase = NextSelectCase(selcase);
509 }
510 break;
511 case EXT:
512 if (ExternalStatMode(s) == ek_method) {
513 Asc_StatErrMsg_NotAllowedDeclarative(fp,s,"");
514 rval = DEF_STAT_MISLOCATED;
515 }
516 break;
517 case REF:
518 break;
519 case COND:
520 tmperr = TypeLintIllegalBodyStats(fp,name,CondStatList(s),
521 (context | context_COND));
522 if (tmperr != DEF_OKAY) {
523 rval = tmperr;
524 }
525 break;
526 /* Stuff illegal in body */
527 case SWITCH:
528 TypeLintError(fp,s,DEF_STAT_MISLOCATED);
529 rval = DEF_STAT_MISLOCATED;
530 FPRINTF(fp," Perhaps SWITCH should be WHEN or SELECT?\n");
531 break;
532 case FLOW: /* fallthrough */
533 case WHILE:
534 TypeLintError(fp,s,DEF_STAT_MISLOCATED);
535 rval = DEF_STAT_MISLOCATED;
536 FPRINTF(fp," Flow controls are allowed only in methods.\n");
537 break;
538 case IF:
539 TypeLintError(fp,s,DEF_STAT_MISLOCATED);
540 rval = DEF_STAT_MISLOCATED;
541 FPRINTF(fp," Perhaps IF should be WHEN or SELECT?\n");
542 break;
543 case RUN:
544 case CALL:
545 case WILLBE:
546 case WBTS:
547 case WNBTS:
548 default:
549 TypeLintError(fp,s,DEF_STAT_MISLOCATED);
550 rval = DEF_STAT_MISLOCATED;
551 }
552 }
553 if (rval != DEF_OKAY && g_tlibs_depth < 2 /* at top */) {
554 FPRINTF(fp," Errors detected in declarative section of '%s'\n",
555 SCP(name));
556 }
557 g_tlibs_depth--;
558 return rval;
559 }
560
561 enum typelinterr TypeLintIllegalParamStats(FILE * fp,
562 symchar *name,
563 CONST struct StatementList *sl)
564 {
565 unsigned long c,len;
566 struct gl_list_t *gl;
567 struct Statement *s;
568 enum typelinterr rval = DEF_OKAY;
569 symchar *tid;
570 CONST struct TypeDescription *t;
571
572 assert(name !=NULL);
573 len = StatementListLength(sl);
574 if (len == 0L) {
575 return rval;
576 }
577 gl = GetList(sl);
578 for(c=1; c<=len;c++) {
579 s = (struct Statement *)gl_fetch(gl,c);
580 switch(StatementType(s)) {
581 case WILLBE:
582 /* check rhs for bad type here */
583 tid = GetStatType(s);
584 t = FindType(tid);
585 switch (GetBaseType(t)) {
586 case relation_type:
587 case logrel_type:
588 case when_type:
589 rval = DEF_ILLEGAL_PARAM;
590 TypeLintError(fp,s,rval);
591 break;
592 case model_type:
593 case patch_type:
594 /* check arg list length. can't do types until after. */
595 if ( SetLength(GetStatTypeArgs(s)) != 0L) {
596 if (TLINT_ERROR) {
597 FPRINTF(fp,
598 "%sArguments defined with WILL_BE cannot " /* no comma */
599 "have arguments. Got %lu.\n",
600 StatioLabel(3),
601 SetLength(GetStatTypeArgs(s)));
602 FPRINTF(fp, "%sYou may want to use WILL_BE_THE_SAME instead.\n",
603 StatioLabel(2));
604 }
605 rval = DEF_ARGDEF_INCORRECT;
606 TypeLintError(fp,s,rval);
607 }
608 break;
609 default:
610 break;
611 }
612 if (VariableListLength(GetStatVarList(s)) > 1L) {
613 rval = DEF_MULTI_PARAM;
614 TypeLintError(fp,s,rval);
615 break; /* no point complaining twice */
616 }
617 /* check simple names */
618 if (CompoundNameInList(GetStatVarList(s)) != -1) {
619 if (TLINT_ERROR) {
620 FPRINTF(fp,"%sCannot use . in defining MODEL arguments.\n",
621 StatioLabel(3));
622 }
623 rval = DEF_NAME_INCORRECT;
624 TypeLintError(fp,s,rval);
625 }
626 break;
627 case ISA:
628 /* check rhs for bad type here */
629 tid = GetStatType(s);
630 t = FindType(tid);
631 if (BaseTypeIsSet(t)==0 && BaseTypeIsConstant(t)==0) {
632 rval = DEF_ILLEGAL_VALPAR;
633 TypeLintError(fp,s,rval);
634 break; /* no point complaining twice */
635 }
636 if (VariableListLength(GetStatVarList(s)) > 1L) {
637 rval = DEF_MULTI_PARAM;
638 TypeLintError(fp,s,rval);
639 break; /* no point complaining twice */
640 }
641 if (CompoundNameInList(GetStatVarList(s)) != -1) {
642 if (TLINT_ERROR) {
643 FPRINTF(fp,"%sCannot create parts in another object with IS_A.\n",
644 StatioLabel(3));
645 FPRINTF(fp," Name %d is incorrect.\n",
646 CompoundNameInList(GetStatVarList(s)));
647 }
648 rval = DEF_NAME_INCORRECT;
649 TypeLintError(fp,s,rval);
650 }
651 break;
652 case ALIASES: /* huge fallthrough */
653 case ARR:
654 case IRT:
655 case ATS:
656 case WBTS:
657 case WNBTS:
658 case AA:
659 case LNK:
660 case UNLNK:
661 case FOR: /* eventually for legal and fk_expect required */
662 case REL:
663 case LOGREL:
664 case ASGN:
665 case CASGN:
666 case WHEN:
667 case FNAME:
668 case SELECT:
669 case SWITCH:
670 case EXT:
671 case REF:
672 case COND:
673 case RUN:
674 case CALL:
675 case FLOW:
676 case WHILE:
677 case IF:
678 default:
679 TypeLintError(fp,s,DEF_STAT_MISLOCATED);
680 rval = DEF_STAT_MISLOCATED;
681 }
682 }
683 if (rval != DEF_OKAY) {
684 FPRINTF(fp," Errors detected in argument definitions of '%s'\n",SCP(name));
685 }
686 return rval;
687 }
688
689 /* could stand to be a lot more rigorous */
690 enum typelinterr
691 TypeLintIllegalWhereStats(FILE * fp,
692 symchar *name,
693 CONST struct StatementList *sl)
694 {
695 unsigned long c,len;
696 struct gl_list_t *gl;
697 struct Statement *s;
698 enum typelinterr rval = DEF_OKAY, tmperr;
699
700 assert(name !=NULL);
701 len = StatementListLength(sl);
702 if (len == 0L) {
703 return rval;
704 }
705 gl = GetList(sl);
706 for(c=1; c<=len;c++) {
707 s = (struct Statement *)gl_fetch(gl,c);
708 switch(StatementType(s)) {
709 case FOR:
710 if (ForLoopKind(s) != fk_check) {
711 rval = DEF_FOR_NOTCHECK;
712 TypeLintError(fp,s,rval);
713 } else {
714 tmperr = TypeLintIllegalWhereStats(fp,name,ForStatStmts(s));
715 if (tmperr != DEF_OKAY) {
716 rval = tmperr;
717 }
718 }
719 break;
720 case WBTS:
721 case WNBTS:
722 case LOGREL:
723 case REL:
724 break;
725 case CASGN:
726 case ALIASES:
727 case ARR:
728 case ISA:
729 case IRT:
730 case ATS:
731 case AA:
732 case LNK:
733 case UNLNK:
734 case ASGN:
735 case WHEN:
736 case FNAME:
737 case SELECT:
738 case SWITCH:
739 case EXT:
740 case REF:
741 case COND:
742 case RUN:
743 case CALL:
744 case IF:
745 case FLOW:
746 case WHILE:
747 case WILLBE:
748 default:
749 TypeLintError(fp,s,DEF_STAT_MISLOCATED);
750 rval = DEF_STAT_MISLOCATED;
751 }
752 }
753 if (rval != DEF_OKAY) {
754 FPRINTF(fp," Errors detected in WHERE statements of '%s'\n",SCP(name));
755 }
756 return rval;
757 }
758
759 enum typelinterr
760 TypeLintIllegalReductionStats(FILE * fp,
761 symchar *name,
762 CONST struct StatementList *sl)
763 {
764 unsigned long c,len;
765 struct gl_list_t *gl;
766 struct Statement *s;
767 enum typelinterr rval = DEF_OKAY;
768
769 assert(name !=NULL);
770 len = StatementListLength(sl);
771 if (len == 0L) {
772 return rval;
773 }
774 gl = GetList(sl);
775 for(c=1; c<=len;c++) {
776 s = (struct Statement *)gl_fetch(gl,c);
777 switch(StatementType(s)) {
778 case CASGN:
779 if (NameCompound(AssignStatVar(s)) != 0) {
780 if (TLINT_ERROR) {
781 FPRINTF(fp,"%sCannot assign parts in an object being passed in.\n",
782 StatioLabel(3));
783 }
784 rval = DEF_NAME_INCORRECT;
785 TypeLintError(fp,s,rval);
786 }
787 break;
788 case ALIASES:
789 case ARR:
790 case ISA:
791 case IRT:
792 case ATS:
793 case WBTS:
794 case WNBTS:
795 case AA:
796 case LNK:
797 case UNLNK:
798 case FOR: /* probably should be legal now and require fk_create */
799 case REL:
800 case LOGREL:
801 case ASGN:
802 case WHEN:
803 case FNAME:
804 case SELECT:
805 case SWITCH:
806 case EXT:
807 case REF:
808 case COND:
809 case RUN:
810 case CALL:
811 case IF:
812 case FLOW:
813 case WHILE:
814 case WILLBE:
815 default:
816 TypeLintError(fp,s,DEF_STAT_MISLOCATED);
817 rval = DEF_STAT_MISLOCATED;
818 }
819 }
820 if (rval != DEF_OKAY) {
821 FPRINTF(fp," Errors detected in parameter assignments of '%s'\n",SCP(name));
822 }
823 return rval;
824 }
825
826 static
827 enum typelinterr
828 TypeLintIllegalMethodStatList(FILE *fp,
829 symchar *name, symchar *pname,
830 struct StatementList *sl,
831 unsigned int context)
832 {
833 unsigned long c,len;
834 struct gl_list_t *gl;
835 struct Statement *s;
836 struct SwitchList *sw;
837 struct StatementList *sublist;
838 enum typelinterr rval = DEF_OKAY, tmperr;
839
840 if (sl == NULL) {
841 return rval;
842 }
843 len = StatementListLength(sl);
844 gl = GetList(sl);
845 for(c=1; c<=len;c++) {
846 s = (struct Statement *)gl_fetch(gl,c);
847 switch(StatementType(s)) {
848 case CASGN:
849 case ALIASES:
850 case ARR:
851 case ISA:
852 case IRT:
853 case ATS:
854 case WBTS:
855 case WNBTS:
856 case AA:
857 case REF:
858 case COND:
859 case WILLBE:
860 case FNAME:
861 Asc_StatErrMsg_NotAllowedMethod(fp,s,"");
862 rval = DEF_STAT_MISLOCATED;
863 break;
864 case REL:
865 case LOGREL:
866 Asc_StatErrMsg_NotAllowedMethod(fp,s,"Perhaps '=' or '==' should be ':='?");
867 rval = DEF_STAT_MISLOCATED;
868 break;
869 case WHEN:
870 Asc_StatErrMsg_NotAllowedMethod(fp,s,"Perhaps WHEN should be SWITCH?");
871 rval = DEF_STAT_MISLOCATED;
872 break;
873 case SELECT:
874 Asc_StatErrMsg_NotAllowedMethod(fp,s,"Perhaps SELECT should be SWITCH?");
875 rval = DEF_STAT_MISLOCATED;
876 break;
877 case FOR:
878 if (ForLoopKind(s) != fk_do) {
879 rval = DEF_FOR_NOTMETH;
880 TypeLintError(fp,s,rval);
881 } else {
882 tmperr = TypeLintIllegalMethodStatList(fp,name,pname,ForStatStmts(s),
883 (context | context_FOR));
884 if (tmperr != DEF_OKAY) {
885 rval = tmperr;
886 }
887 }
888 break;
889 case EXT:
890 if (ExternalStatMode(s) != ek_method) {
891 Asc_StatErrMsg_NotAllowedMethod(fp,s,"");
892 rval = DEF_STAT_MISLOCATED;
893 }
894 break;
895 case LNK:
896 case UNLNK:
897 /* DS: in case we provide functionality for other statements inside LINK, check their legal status */
898 /* DS: in case we provide functionality for other statements inside UNLINK, check their legal status */
899 break;
900 case ASGN:
901 case RUN:
902 case FIX:
903 case FREE:
904 case CALL:
905 case SOLVER:
906 case OPTION:
907 case SOLVE:
908 break;
909 case WHILE:
910 if (WhileStatBlock(s) != NULL) {
911 tmperr = TypeLintIllegalMethodStatList(fp,name,pname,WhileStatBlock(s),
912 (context | context_WHILE));
913 if (tmperr != DEF_OKAY) {
914 rval = tmperr;
915 break;
916 }
917 }
918 break;
919 case ASSERT:
920 /* no sublists for TEST */
921 break;
922
923 case IF:
924 if (IfStatThen(s) != NULL) {
925 tmperr = TypeLintIllegalMethodStatList(fp,name,pname,IfStatThen(s),
926 (context | context_IF));
927 if (tmperr != DEF_OKAY) {
928 rval = tmperr;
929 break;
930 }
931 }
932 if (IfStatElse(s) != NULL){
933 tmperr = TypeLintIllegalMethodStatList(fp,name,pname,IfStatElse(s),
934 (context | context_IF));
935 if (tmperr != DEF_OKAY) {
936 rval = tmperr;
937 }
938 }
939 break;
940 case SWITCH:
941 sw = SwitchStatCases(s);
942 while (sw!=NULL) {
943 sublist = SwitchStatementList(sw);
944 if (sublist!=NULL) {
945 tmperr = TypeLintIllegalMethodStatList(fp,name,pname,sublist,
946 (context | context_SWITCH));
947 if (tmperr != DEF_OKAY) {
948 rval = tmperr;
949 break;
950 }
951 }
952 sw = NextSwitchCase(sw);
953 }
954 break;
955 case FLOW:
956 switch (FlowStatControl(s)) {
957 case fc_break:
958 if ((context & (context_FOR | context_SWITCH | context_WHILE))==0) {
959 rval = DEF_ILLEGAL_BREAK;
960 TypeLintError(fp,s,rval);
961 }
962 break;
963 case fc_continue:
964 if ((context & (context_FOR | context_WHILE))==0) {
965 rval = DEF_ILLEGAL_CONTINUE;
966 TypeLintError(fp,s,rval);
967 }
968 break;
969 case fc_fallthru:
970 if ((context & context_SWITCH)==0) {
971 rval = DEF_ILLEGAL_FALLTHRU;
972 TypeLintError(fp,s,rval);
973 }
974 break;
975 case fc_return:
976 case fc_stop:
977 break;
978 }
979 break;
980 default:
981 rval = DEF_UNKNOWN_ERR;
982 TypeLintError(fp,s,rval);
983 break;
984 }
985 }
986 if (rval != DEF_OKAY) {
987 FPRINTF(fp," Errors detected in METHOD '%s' of '%s'\n",SCP(pname),SCP(name));
988 }
989 return rval;
990 }
991
992 enum typelinterr TypeLintIllegalMethodStats(FILE * fp,
993 symchar *name,
994 struct gl_list_t *pl,
995 unsigned int context)
996 {
997 unsigned long pc,plen;
998 struct StatementList *sl;
999 symchar *pname;
1000 enum typelinterr rval = DEF_OKAY, tmperr;
1001
1002 assert(name != NULL);
1003 if (pl == NULL) {
1004 return rval;
1005 }
1006 plen = gl_length(pl);
1007 for (pc=1; pc <= plen; pc++) {
1008 sl = ProcStatementList((struct InitProcedure *)gl_fetch(pl,pc));
1009 pname= ProcName((struct InitProcedure *)gl_fetch(pl,pc));
1010 tmperr = TypeLintIllegalMethodStatList(fp,name,pname,sl,context);
1011 if (tmperr != DEF_OKAY) {
1012 rval = tmperr;
1013 printf("asdsaf \n");
1014 }
1015 }
1016 return rval;
1017 }

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22