Explorar o código

revised the treatment of "e op= f" expression

erikb %!s(int64=38) %!d(string=hai) anos
pai
achega
736a5ff99b

+ 1 - 0
lang/cem/cemcom/Files

@@ -75,6 +75,7 @@ statement.g
 stb.c
 storage.c
 storage.h
+stmt.str
 struct.c
 struct.str
 switch.c

+ 37 - 67
lang/cem/cemcom/ch7.c

@@ -192,9 +192,6 @@ ch7cast(expp, oper, tp)
 	if ((*expp)->ex_class == String)
 		string2pointer(expp);
 	oldtp = (*expp)->ex_type;
-	if (oldtp == tp)
-		{}			/* life is easy */
-	else
 #ifndef NOBITFIELD
 	if (oldtp->tp_fund == FIELD)	{
 		field2arith(expp);
@@ -205,6 +202,9 @@ ch7cast(expp, oper, tp)
 		ch7cast(expp, oper, tp->tp_up);
 	else
 #endif NOBITFIELD
+	if (oldtp == tp)
+		{}			/* life is easy */
+	else
 	if (tp->tp_fund == VOID)	/* Easy again */
 		(*expp)->ex_type = void_type;
 	else
@@ -311,6 +311,17 @@ ch7asgn(expp, oper, expr)
 	struct expr *expr;
 {
 	/*	The assignment operators.
+		"f op= e" should be interpreted as
+		"f = (typeof f)((typeof (f op e))f op (typeof (f op e))e)"
+		and not as "f = f op (typeof f)e".
+		Consider, for example, (i == 10) i *= 0.9; (i == 9), where
+		typeof i == int.
+		The resulting expression tree becomes:
+				op=
+				/ \
+			       /   \
+			      f     (typeof (f op e))e
+		EVAL should however take care of evaluating (typeof (f op e))f
 	*/
 	int fund = (*expp)->ex_type->tp_fund;
 
@@ -320,48 +331,30 @@ ch7asgn(expp, oper, expr)
 		(*expp)->ex_depth = 99;	/* no direct store/load at EVAL() */
 			/* what is 99 ??? DG */
 	}
-	switch (oper)	{
-	case '=':
+	if (oper == '=') {
 		ch7cast(&expr, oper, (*expp)->ex_type);
-		break;
-	case TIMESAB:
-	case DIVAB:
-	case MODAB:
-		check_arith_type(expp, oper);
-		any2arith(&expr, oper);
-		ch7cast(&expr, CAST, (*expp)->ex_type);
-		break;
-	case PLUSAB:
-	case MINAB:
-		any2arith(&expr, oper);
-		if (fund == POINTER)	{
-			check_integral_type(&expr, oper);
-			ch7bin(&expr, '*',
-				intexpr(
-					size_of_type(
-						(*expp)->ex_type->tp_up,
-						"object"
-					),
-					pa_type->tp_fund
-				)
-			);
-		}
-		else	{
-			check_arith_type(expp, oper);
-			ch7cast(&expr, CAST, (*expp)->ex_type);
+	}
+	else {	/* turn e into e' where typeof(e') = typeof (f op e) */
+		struct expr *extmp = intexpr(0, INT);
+
+		/* this is really $#@&*%$# ! */
+		extmp->ex_lvalue = 1;
+		extmp->ex_type = (*expp)->ex_type;
+		ch7bin(&extmp, oper, expr);
+		/* note that ch7bin creates a tree of the expression
+			((typeof (f op e))f op (typeof (f op e))e),
+		   where f ~ extmp and e ~ expr;
+		   we have to use (typeof (f op e))e
+		   Ch7bin does not create a tree if both operands
+		   were illegal or constants!
+		*/
+		if (extmp->ex_class == Oper) {
+			expr = extmp->OP_RIGHT;
+			extmp->OP_RIGHT = NILEXPR;
+			free_expression(extmp);
 		}
-		break;
-	case LEFTAB:
-	case RIGHTAB:
-		check_integral_type(expp, oper);
-		ch7cast(&expr, oper, int_type);
-		break;
-	case ANDAB:
-	case XORAB:
-	case ORAB:
-		check_integral_type(expp, oper);
-		ch7cast(&expr, oper, (*expp)->ex_type);
-		break;
+		else
+			expr = extmp;
 	}
 #ifndef NOBITFIELD
 	if (fund == FIELD)
@@ -369,6 +362,7 @@ ch7asgn(expp, oper, expr)
 	else
 #endif NOBITFIELD
 		*expp = new_oper((*expp)->ex_type, *expp, oper, expr);
+	(*expp)->OP_TYPE = expr->ex_type;	/* for EVAL() */
 }
 
 /*	Some interesting (?) questions answered.
@@ -393,18 +387,6 @@ is_integral_type(tp)
 	}
 }
 
-check_integral_type(expp, oper)
-	struct expr **expp;
-{
-	register struct expr *expr = *expp;
-	
-	if (!is_integral_type(expr->ex_type))	{
-		expr_error(expr, "%s on non-integral type (%s)",
-			symbol2str(oper), symbol2str(expr->ex_type->tp_fund));
-		erroneous2int(expp);
-	}
-}
-
 int
 is_arith_type(tp)
 	struct type *tp;
@@ -426,15 +408,3 @@ is_arith_type(tp)
 		return 0;
 	}
 }
-
-check_arith_type(expp, oper)
-	struct expr **expp;
-{
-	register struct expr *expr = *expp;
-	
-	if (!is_arith_type(expr->ex_type))	{
-		expr_error(expr, "%s on non-arithmetical type (%s)",
-			symbol2str(oper), symbol2str(expr->ex_type->tp_fund));
-		erroneous2int(expp);
-	}
-}

+ 33 - 3
lang/cem/cemcom/ch7bin.c

@@ -24,6 +24,7 @@ ch7bin(expp, oper, expr)
 	struct expr *expr;
 {
 	/*	apply binary operator oper between *expp and expr.
+		NB: don't swap operands if op is one of the op= operators!!!
 	*/
 	any2opnd(expp, oper);
 	any2opnd(&expr, oper);
@@ -79,15 +80,24 @@ ch7bin(expp, oper, expr)
 		*expp = new_oper(expr->ex_type, *expp, PARCOMMA, expr);
 		break;
 	case '%':
+	case MODAB:
+/*** NB  "not float" means "integral" !!!
 		fund = arithbalance(expp, oper, &expr);
 		if (fund == DOUBLE)	{
-			expr_error(*expp, "floating operand to %%");
+			expr_error(*expp, "floating operand to %s", 
+				symbol2str(oper));
 			erroneous2int(expp);
 		}
 		else
 			non_commutative_binop(expp, oper, expr);
+***/
+		opnd2integral(expp, oper);
+		opnd2integral(&expr, oper);
+		fund = arithbalance(expp, oper, &expr);
+		non_commutative_binop(expp, oper, expr);
 		break;
 	case '/':
+	case DIVAB:
 		fund = arithbalance(expp, oper, &expr);
 		non_commutative_binop(expp, oper, expr);
 		break;
@@ -95,6 +105,10 @@ ch7bin(expp, oper, expr)
 		fund = arithbalance(expp, oper, &expr);
 		commutative_binop(expp, oper, expr);
 		break;
+	case TIMESAB:
+		fund = arithbalance(expp, oper, &expr);
+		non_commutative_binop(expp, oper, expr);
+		break;
 	case '+':
 		if (expr->ex_type->tp_fund == POINTER)	{
 			/* swap operands */
@@ -102,6 +116,8 @@ ch7bin(expp, oper, expr)
 			expr = *expp;
 			*expp = etmp;
 		}
+		/*FALLTHROUGH*/
+	case PLUSAB:
 		if ((*expp)->ex_type->tp_fund == POINTER)	{
 			pointer_arithmetic(expp, oper, &expr);
 			if (	expr->ex_type->tp_size !=
@@ -113,10 +129,14 @@ ch7bin(expp, oper, expr)
 		}
 		else	{
 			fund = arithbalance(expp, oper, &expr);
-			commutative_binop(expp, oper, expr);
+			if (oper == '+')
+				commutative_binop(expp, oper, expr);
+			else
+				non_commutative_binop(expp, oper, expr);
 		}
 		break;
 	case '-':
+	case MINAB:
 		if ((*expp)->ex_type->tp_fund == POINTER)	{
 			if (expr->ex_type->tp_fund == POINTER)
 				pntminuspnt(expp, oper, expr);
@@ -131,7 +151,9 @@ ch7bin(expp, oper, expr)
 		}
 		break;
 	case LEFT:
+	case LEFTAB:
 	case RIGHT:
+	case RIGHTAB:
 		opnd2integral(expp, oper);
 		opnd2integral(&expr, oper);
 		ch7cast(&expr, oper, int_type); /* leftop should be int	*/
@@ -152,9 +174,17 @@ ch7bin(expp, oper, expr)
 	case '|':
 		opnd2integral(expp, oper);
 		opnd2integral(&expr, oper);
-		fund = arithbalance(expp, oper, &expr);	/* <===	*/
+		fund = arithbalance(expp, oper, &expr);
 		commutative_binop(expp, oper, expr);
 		break;
+	case ANDAB:
+	case XORAB:
+	case ORAB:
+		opnd2integral(expp, oper);
+		opnd2integral(&expr, oper);
+		fund = arithbalance(expp, oper, &expr);
+		non_commutative_binop(expp, oper, expr);
+		break;
 	case AND:
 	case OR:
 		opnd2test(expp, oper);

+ 1 - 0
lang/cem/cemcom/conversion.c

@@ -115,6 +115,7 @@ fundamental(tp)
 	case CHAR:
 	case SHORT:
 	case INT:
+	case ERRONEOUS:
 	case LONG:
 	case ENUM:
 		return tp->tp_unsigned ? T_UNSIGNED : T_SIGNED;

+ 6 - 2
lang/cem/cemcom/dumpidf.c

@@ -271,9 +271,10 @@ type2str(tp)
 			if (tp->tp_field)	{
 				struct field *fd = tp->tp_field;
 				
-				sprint(buf, "%s [s=%ld,w=%ld]", buf,
+				sprint(buf, "%s [s=%ld,w=%ld] of ", buf,
 					fd->fd_shift, fd->fd_width);
 			}
+			else
 #endif NOBITFIELD
 			ops = 0;
 			break;
@@ -367,7 +368,10 @@ p1_expr(lvl, expr)
 		o = &expr->ex_object.ex_oper;
 		print("\n");
 		p1_expr(lvl+1, o->op_left);
-		p1_indent(lvl); print("%s\n", symbol2str(o->op_oper));
+		p1_indent(lvl);
+		print("%s <%s>\n", symbol2str(o->op_oper),
+			type2str(o->op_type)
+		);
 		p1_expr(lvl+1, o->op_right);
 		break;
 	case Type:

+ 10 - 4
lang/cem/cemcom/eval.c

@@ -389,27 +389,33 @@ EVAL(expr, val, code, true_label, false_label)
 				C_sti(pointer_size);
 				C_lal(tmpvar);
 				C_loi(pointer_size);
-				C_loi(tp->tp_size);
+				C_loi(leftop->ex_type->tp_size);
+				conversion(leftop->ex_type, tp);
 				EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
 				assop(tp, oper);
+				conversion(tp, leftop->ex_type);
 				if (gencode)
-					C_dup(roundup(tp->tp_size));
+					C_dup(roundup(leftop->ex_type->tp_size));
 				C_lal(tmpvar);
 				C_loi(pointer_size);
-				C_sti(tp->tp_size);
+				C_sti(leftop->ex_type->tp_size);
 				free_tmp_var(old_offset);
 			}
 			else	{
 				load_val(leftop, RVAL);
+				conversion(leftop->ex_type, tp);
 				EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
 				assop(tp, oper);
+				conversion(tp, leftop->ex_type);
 				if (gencode)
-					C_dup(roundup(tp->tp_size));
+					C_dup(roundup(leftop->ex_type->tp_size));
 				store_val(
 					&(leftop->ex_object.ex_value),
 					leftop->ex_type
 				);
 			}
+			if (gencode)
+				conversion(leftop->ex_type, expr->ex_type);
 			break;
 		case '(':
 		{

+ 18 - 16
lang/cem/cemcom/field.c

@@ -40,13 +40,16 @@ eval_field(expr, code)
 	struct type *tp = leftop->ex_type->tp_up;
 	arith old_offset, tmpvar;
 
-	/*	The type in which the bitfield arithmetic is done:
+	/*	The type in which the bitfield arithmetic is done;
+		AND IN WHICH BITFIELDS ARE STORED!
 	*/
 	struct type *atype = tp->tp_unsigned ? uword_type : word_type;
 	arith asize = atype->tp_size;
 
-	ASSERT(leftop->ex_type->tp_fund == FIELD);
+	/* First some assertions to be sure that the rest is legal */
 	ASSERT(asize == word_size);	/* make sure that C_loc() is legal */
+	ASSERT(leftop->ex_type->tp_fund == FIELD);
+
 	leftop->ex_type = atype;	/* this is cheating but it works... */
 
 	/*	Note that op is either an assignment operator or an increment/
@@ -55,6 +58,8 @@ eval_field(expr, code)
 	if (op == '=') {
 		/*	F = E: f = ((E & mask)<<shift) | (~(mask<<shift) & f)
 		*/
+		ASSERT(tp == rightop->ex_type);
+
 		EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
 		conversion(tp, atype);
 		C_loc(fd->fd_mask);
@@ -71,10 +76,7 @@ eval_field(expr, code)
 			load_val(leftop, RVAL);
 			C_and(asize);
 			C_ior(asize);
-			store_val(
-				&(leftop->ex_object.ex_value),
-				leftop->ex_type
-			);
+			store_val(&(leftop->ex_object.ex_value), atype);
 		}
 		else	{			/* complex case	*/
 			tmpvar = tmp_pointer_var(&old_offset);
@@ -114,16 +116,19 @@ eval_field(expr, code)
 		C_and(asize);
 		if (code == TRUE && (op == POSTINCR || op == POSTDECR))
 			C_dup(asize);
+
+		/* the 'op' operation: */
+		conversion(atype, rightop->ex_type);
 		EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
-		conversion(tp, atype);
-		/* generate code for the operator */
 		if (op == PLUSPLUS || op == POSTINCR)
-			assop(atype, PLUSAB);
+			assop(rightop->ex_type, PLUSAB);
 		else
 		if (op == MINMIN || op == POSTDECR)
-			assop(atype, MINAB);
+			assop(rightop->ex_type, MINAB);
 		else
-			assop(atype, op);
+			assop(rightop->ex_type, op);
+		conversion(rightop->ex_type, atype);
+
 		C_loc(fd->fd_mask);
 		C_and(asize);
 		if (code == TRUE && op != POSTINCR && op != POSTDECR)
@@ -138,10 +143,7 @@ eval_field(expr, code)
 			load_val(leftop, RVAL);
 			C_and(asize);
 			C_ior(asize);
-			store_val(
-				&(leftop->ex_object.ex_value),
-				leftop->ex_type
-			);
+			store_val(&(leftop->ex_object.ex_value), atype);
 		}
 		else	{
 			C_lal(tmpvar);
@@ -168,7 +170,7 @@ eval_field(expr, code)
 			C_loc(shift);
 			C_sri(asize);
 		}
-		conversion(atype, tp);
+		conversion(atype, expr->ex_type);
 	}
 }
 #endif NOBITFIELD