newer version
This commit is contained in:
		
							parent
							
								
									629b8fdb88
								
							
						
					
					
						commit
						6ff4d852e1
					
				
					 8 changed files with 190 additions and 22 deletions
				
			
		|  | @ -50,6 +50,8 @@ chk_expr(expp, const) | |||
| 		return chk_call(expp, const); | ||||
| 	case Link: | ||||
| 		return chk_name(expp, const); | ||||
| 	default: | ||||
| 		assert(0); | ||||
| 	} | ||||
| 	/*NOTREACHED*/ | ||||
| } | ||||
|  | @ -58,7 +60,85 @@ int | |||
| chk_set(expp, const) | ||||
| 	register struct node *expp; | ||||
| { | ||||
| 	/* ??? */ | ||||
| 	struct type *tp; | ||||
| 	struct def *df; | ||||
| 	register struct node *nd; | ||||
| 	extern struct def *findname(); | ||||
| 
 | ||||
| 	assert(expp->nd_symb == SET); | ||||
| 
 | ||||
| 	/* First determine the type of the set
 | ||||
| 	*/ | ||||
| 	if (expp->nd_left) { | ||||
| 		/* A type was given. Check it out
 | ||||
| 		*/ | ||||
| 		df = findname(expp->nd_left); | ||||
| 		if ((df->df_kind != D_TYPE && df->df_kind != D_ERROR) || | ||||
| 		    (df->df_type->tp_fund != SET)) { | ||||
| 			node_error(expp, "Illegal set type"); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		tp = df->df_type; | ||||
| 	} | ||||
| 	else	tp = bitset_type; | ||||
| 
 | ||||
| 	/* Now check the elements given
 | ||||
| 	*/ | ||||
| 	nd = expp->nd_right; | ||||
| 	while (nd) { | ||||
| 		assert(nd->nd_class == Link && nd->nd_symb == ','); | ||||
| 		if (!chk_el(nd->nd_left, const, tp->next, 0)) return 0; | ||||
| 		nd = nd->nd_right; | ||||
| 	} | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| chk_el(expp, const, tp, level) | ||||
| 	struct node *expp; | ||||
| 	struct type *tp; | ||||
| { | ||||
| 	/*	Check elements of a set. This routine may call itself
 | ||||
| 		recursively, but only once. | ||||
| 	*/ | ||||
| 	if (expp->nd_class == Link && expp->nd_symb == UPTO) { | ||||
| 		/*  { ... , expr1 .. expr2,  ... } */ | ||||
| 		if (level) { | ||||
| 			node_error(expp, "Illegal set element"); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		if (!chk_el(expp->nd_left, const, tp, 1) || | ||||
| 		    !chk_el(expp->nd_right, const, tp, 1)) { | ||||
| 			return 0; | ||||
| 		} | ||||
| 		if (expp->nd_left->nd_class == Value && | ||||
| 		    expp->nd_right->nd_class == Value) { | ||||
| 		    	if (expp->nd_left->nd_INT > expp->nd_right->nd_INT) { | ||||
| node_error(expp, "Lower bound exceeds upper bound in range"); | ||||
| 				return 0; | ||||
| 			} | ||||
| 		} | ||||
| 		return 1; | ||||
| 	} | ||||
| 	if (!chk_expr(expp, const)) return 0; | ||||
| 	if (!TstCompat(tp, expp->nd_type)) { | ||||
| 		node_error(expp, "Set element has incompatible type"); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	if (expp->nd_class == Value) { | ||||
| 	    	if ((tp->tp_fund != ENUMERATION && | ||||
| 		     (expp->nd_INT < tp->sub_lb || expp->nd_INT > tp->sub_ub)) | ||||
| 		   || | ||||
| 		    (tp->tp_fund == ENUMERATION && | ||||
| 		     (expp->nd_INT < 0 || expp->nd_INT > tp->enm_ncst)) | ||||
| 		   ) { | ||||
| 			node_error(expp, "Set element out of range"); | ||||
| #ifdef DEBUG | ||||
| 			debug("%d (%d, %d)", (int) expp->nd_INT, (int) tp->sub_lb, (int) tp->sub_ub); | ||||
| #endif | ||||
| 			return 0; | ||||
| 		} | ||||
| 	} | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,5 +8,4 @@ extern int | |||
| 	mach_long_size;	/* size of long on this machine == sizeof(long) */ | ||||
| extern arith | ||||
| 	max_int,	/* maximum integer on target machine	*/ | ||||
| 	max_unsigned,	/* maximum unsigned on target machine	*/ | ||||
| 	max_longint;	/* maximum longint on target machine	*/ | ||||
| 	max_unsigned;	/* maximum unsigned on target machine	*/ | ||||
|  |  | |||
|  | @ -267,10 +267,10 @@ init_cst() | |||
| 	} | ||||
| 	mach_long_size = i; | ||||
| 	mach_long_sign = 1 << (mach_long_size * 8 - 1); | ||||
| 	if (sizeof(long) < mach_long_size) | ||||
| 	if (int_size > mach_long_size) { | ||||
| 		fatal("sizeof (long) insufficient on this machine"); | ||||
| 	} | ||||
| 
 | ||||
| 	max_int = full_mask[int_size] & ~(1 << (int_size * 8 - 1)); | ||||
| 	max_longint = full_mask[lint_size] & ~(1 << (lint_size * 8 - 1)); | ||||
| 	max_unsigned = full_mask[int_size]; | ||||
| } | ||||
|  |  | |||
|  | @ -233,8 +233,8 @@ IdentList(struct node **p;) | |||
| 
 | ||||
| SubrangeType(struct type **ptp;) | ||||
| { | ||||
| 	struct type *tp; | ||||
| 	struct node *nd1 = 0, *nd2 = 0; | ||||
| 	struct node *nd1, *nd2; | ||||
| 	extern struct type *subr_type(); | ||||
| }: | ||||
| 	/* | ||||
| 	   This is not exactly the rule in the new report, but see | ||||
|  | @ -243,17 +243,7 @@ SubrangeType(struct type **ptp;) | |||
| 	'[' ConstExpression(&nd1) | ||||
| 	UPTO ConstExpression(&nd2) | ||||
| 	']' | ||||
| 	/* | ||||
| 	   Evaluate the expressions. Check that they are indeed constant. | ||||
| 	   ??? | ||||
| 	   Leave the basetype of the subrange in tp; | ||||
| 	*/ | ||||
| 			{ | ||||
| 			  /* For the time being: */ | ||||
| 			  tp = int_type; | ||||
| 			  tp = construct_type(SUBRANGE, tp); | ||||
| 			  *ptp = tp; | ||||
| 			} | ||||
| 			{ *ptp = subr_type(nd1, nd2); } | ||||
| ; | ||||
| 
 | ||||
| ArrayType(struct type **ptp;) | ||||
|  | @ -350,10 +340,11 @@ CaseLabels | |||
| SetType(struct type **ptp;) | ||||
| { | ||||
| 	struct type *tp; | ||||
| 	struct type *set_type(); | ||||
| } : | ||||
| 	SET OF SimpleType(&tp) | ||||
| 			{  | ||||
| 			  *ptp = construct_type(SET, tp); | ||||
| 			  *ptp = set_type(tp); | ||||
| 			} | ||||
| ; | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,6 +25,7 @@ GetFile(name) | |||
| 	*/ | ||||
| 	extern char *DEFPATH[]; | ||||
| 	char buf[256]; | ||||
| 	char *strcpy(), *strcat(); | ||||
| 
 | ||||
| 	(void) strcpy(buf, name); | ||||
| 	if (strlen(buf) > 10) { | ||||
|  |  | |||
|  | @ -91,6 +91,7 @@ ConstExpression(struct node **pnd;): | |||
| 		     ( debug("Constant expression:"), | ||||
| 		       PrNode(*pnd))); | ||||
| 		  (void) chk_expr(*pnd, 1); | ||||
| 		  DO_DEBUG(3, PrNode(*pnd)); | ||||
| 		} | ||||
| ; | ||||
| 
 | ||||
|  |  | |||
|  | @ -13,6 +13,8 @@ static char *RcsId = "$Header$"; | |||
| #include	"idf.h" | ||||
| #include	"LLlex.h" | ||||
| #include	"node.h" | ||||
| #include	"const.h" | ||||
| #include	"debug.h" | ||||
| 
 | ||||
| /*	To be created dynamically in main() from defaults or from command
 | ||||
| 	line parameters. | ||||
|  | @ -129,6 +131,7 @@ init_types() | |||
| 	register struct type *tp; | ||||
| 
 | ||||
| 	char_type = standard_type(CHAR, 1, (arith) 1); | ||||
| 	char_type->enm_ncst = 256; | ||||
| 	bool_type = standard_type(BOOLEAN, 1, (arith) 1); | ||||
| 	int_type = standard_type(INTEGER, int_align, int_size); | ||||
| 	longint_type = standard_type(LONGINT, lint_align, lint_size); | ||||
|  | @ -217,8 +220,87 @@ chk_basesubrange(tp, base) | |||
| 	else if (base != card_type && base != int_type) { | ||||
| 		error("Illegal base for a subrange"); | ||||
| 	} | ||||
| 	else if (base == int_type && tp->next == card_type && | ||||
| 		 (tp->sub_ub > max_int || tp->sub_ub)) { | ||||
| 		error("Upperbound to large for type INTEGER"); | ||||
| 	} | ||||
| 	else if (base != tp->next && base != int_type) { | ||||
| 		error("Specified base does not conform"); | ||||
| 	} | ||||
| 	tp->next = base; | ||||
| } | ||||
| 
 | ||||
| struct type * | ||||
| subr_type(lb, ub) | ||||
| 	struct node *lb, *ub; | ||||
| { | ||||
| 	/*	Construct a subrange type from the constant expressions
 | ||||
| 		indicated by "lb" and "ub", but first perform some | ||||
| 		checks | ||||
| 	*/ | ||||
| 	register struct type *tp = lb->nd_type; | ||||
| 
 | ||||
| 	if (!TstCompat(lb->nd_type, ub->nd_type)) { | ||||
| 		node_error(ub, "Types of subrange bounds not compatible"); | ||||
| 		return error_type; | ||||
| 	} | ||||
| 
 | ||||
| 	if (tp->tp_fund == SUBRANGE) tp = tp->next; | ||||
| 	if (tp == intorcard_type) tp = card_type;	/* lower bound > 0 */ | ||||
| 
 | ||||
| 	/* Check base type
 | ||||
| 	*/ | ||||
| 	if (tp != int_type && tp != card_type && tp != char_type && | ||||
| 	    tp->tp_fund != ENUMERATION) { | ||||
| 		/* BOOLEAN is also an ENUMERATION type
 | ||||
| 		*/ | ||||
| 		node_error(ub, "Illegal base type for subrange"); | ||||
| 		return error_type; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Check bounds
 | ||||
| 	*/ | ||||
| 	if (lb->nd_INT > ub->nd_INT) { | ||||
| 		node_error(ub, "Lower bound exceeds upper bound"); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Now construct resulting type
 | ||||
| 	*/ | ||||
| 	tp = construct_type(SUBRANGE, tp); | ||||
| 	tp->sub_lb = lb->nd_INT; | ||||
| 	tp->sub_ub = ub->nd_INT; | ||||
| 	DO_DEBUG(2,debug("Creating subrange type %ld-%ld", (long)lb->nd_INT,(long)ub->nd_INT)); | ||||
| 	return tp; | ||||
| } | ||||
| #define MAX_SET	1024	/* ??? Maximum number of elements in a set */ | ||||
| 
 | ||||
| struct type * | ||||
| set_type(tp) | ||||
| 	struct type *tp; | ||||
| { | ||||
| 	/*	Construct a set type with base type "tp", but first
 | ||||
| 		perform some checks | ||||
| 	*/ | ||||
| 	int lb, ub; | ||||
| 
 | ||||
| 	if (tp->tp_fund == SUBRANGE) { | ||||
| 		if ((lb = tp->sub_lb) < 0 || (ub = tp->sub_ub) > MAX_SET - 1) { | ||||
| 			error("Set type limits exceeded"); | ||||
| 			return error_type; | ||||
| 		} | ||||
| 	} | ||||
| 	else if (tp->tp_fund == ENUMERATION || tp == char_type) { | ||||
| 		lb = 0; | ||||
| 		if ((ub = tp->enm_ncst - 1) > MAX_SET - 1) { | ||||
| 			error("Set type limits exceeded"); | ||||
| 			return error_type; | ||||
| 		} | ||||
| 	} | ||||
| 	else { | ||||
| 		error("illegal base type for set"); | ||||
| 		return error_type; | ||||
| 	} | ||||
| 	tp = construct_type(SET, tp); | ||||
| 	tp->tp_size = align(((ub - lb) + 7)/8, wrd_align); | ||||
| 	return tp; | ||||
| } | ||||
|  |  | |||
|  | @ -19,6 +19,10 @@ TstTypeEquiv(tp1, tp2) | |||
| 	*/ | ||||
| 
 | ||||
| 	return     tp1 == tp2 | ||||
| 		|| | ||||
| 		   tp1 == error_type | ||||
| 		|| | ||||
| 		   tp2 == error_type | ||||
| 		|| | ||||
| 		   (  | ||||
| 		     tp1 && tp1->tp_fund == PROCEDURE | ||||
|  | @ -61,9 +65,19 @@ TstCompat(tp1, tp2) | |||
| 		Modula-2 Report for a definition of "compatible". | ||||
| 	*/ | ||||
| 	if (TstTypeEquiv(tp1, tp2)) return 1; | ||||
| 	if (tp2->tp_fund == SUBRANGE) tp1 = tp1->next; | ||||
| 	if (tp2->tp_fund == SUBRANGE) tp1 = tp1->next; | ||||
| 	if (tp1->tp_fund == SUBRANGE) tp1 = tp1->next; | ||||
| 	if (tp2->tp_fund == SUBRANGE) tp2 = tp2->next; | ||||
| 	return	tp1 == tp2 | ||||
| 	    || | ||||
| 		(  tp1 == intorcard_type | ||||
| 		&& | ||||
| 		   (tp2 == int_type || tp2 == card_type) | ||||
| 		) | ||||
| 	    || | ||||
| 		(  tp2 == intorcard_type | ||||
| 		&& | ||||
| 		   (tp1 == int_type || tp1 == card_type) | ||||
| 		) | ||||
| 	    || | ||||
| 		(  tp1 == address_type | ||||
| 		&&  | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue