Page 1 of 2

MAX with two arguments

Posted: Sat Aug 22, 2020 1:40 am
by Ivan Denisov
Oleg found

Code: Select all

MODULE TestCP;

CONST
  max* = MAX(INTEGER, 0);

END TestCP.
This invalid code gives not error.

Re: MAX with two arguments

Posted: Sat Aug 22, 2020 8:27 am
by adimetrius
Great finding, Ivan!

Looks like a small omission in DevCPB.StFct, I think it can be fixed as follows:

Code: Select all

ELSIF (fctno = minfn) OR (fctno = maxfn) THEN
	IF (parno < 1) OR (parno = 1) & (p.hint # 1) THEN err(65) 
	(* add this branch *) ELSIF (p.hint = 1) & (parno > 1) THEN err(64)
	END;
p.hint is filled out in StPar0 when analyzing the first actual parameter to MAX/MIN, and .hint = 1 indicates the 1st actual parameter was a type. parno is the total number of actual parameters passed to the predeclared procedure. 65 is 'not enough parameters', 64 is 'too many parameters'.

The fix also covers MAX(REAL, ?), etc., as well as MIN.

Re: MAX with two arguments

Posted: Sun Aug 23, 2020 2:09 am
by Zorko
adimetrius, I tested your fix and found it perfectly. Thank you!

In descritpion of CPlang of MIN and MAX with two arguments:

Code: Select all

MAX(x, y)	<= INTEGER	INTEGER	the larger value of x and y
	integer type	LONGINT
	<= SHORTREAL	SHORTREAL
	numeric type	REAL
	SHORTCHAR	SHORTCHAR
	character type	CHAR
MIN(x, y)	<= INTEGER	INTEGER	the smaller of x and y
	integer type	LONGINT
	<= SHORTREAL	SHORTREAL
	numeric type	REAL
	SHORTCHAR	SHORTCHAR
	character type	CHAR
As you can see, the documentation describes support for the characters. However I can't compile such code with definition MIN/MAX(characters) as a constant:

Code: Select all

CONST
	max* = MAX("s", "a"); <-- operand inapplicable to (this) function
I'm sure it's a small omission, too.

In expression it compiles:

Code: Select all

VAR c1, c2: CHAR;
BEGIN
	c1 := MIN(c1, c2);
I do propose this fix:

CPB.ConstOp

Code: Select all

		| min:
-				IF f IN intSet + realSet THEN
+				IF f IN intSet + realSet + charSet THEN
		| max:
-				IF f IN intSet + realSet THEN
+				IF f IN intSet + realSet + charSet THEN

Re: MAX with two arguments

Posted: Mon Aug 24, 2020 8:29 am
by Zinn
Sorry Ivan, that is not a mistake. In the Language Report capitel 10.3 Predeclared Procedures there define

MAX(T) T = basic type T maximum value of type T
T = SET INTEGER maximum element of a set

MAX(x, y) <= INTEGER INTEGER the larger value of x and y
integer type LONGINT
<= SHORTREAL SHORTREAL
numeric type REAL
SHORTCHAR SHORTCHAR
character type CHAR

So there is no need to change the Compiler. It works as it is defined.
- Helmut

Re: MAX with two arguments

Posted: Mon Aug 24, 2020 9:20 am
by adimetrius
Helmut,

will all due respect, this is not how I read the Language report capitel 10.3.

Also, for MAX(a, b) to be defined, '<' (less) has to be defined for a and b also (precisely speaking, '<' has to be defined for pairs a, b and b, a), because
IF a <= b THEN MAX(a, b) = a
ELSE MAX(a, b) = b

Can you say that INTEGER < 0? Or is it rather that INTEGER > 0? Maybe INTEGER = 0? Clearly, '<' is not defined for INTEGER, 0.

Thus, mathematically speaking, MAX(INTEGER, 0) does not make sense. Though MAX(MAX(INTEGER), 0) makes perfect sense.

Also, I've tried to search for 'MAX(INTEGER,' accross BlackBox sources, with no result.

All this to say, I don't think MAX(INTEGER, 0) was meant to be valid by the language authors.

Re: MAX with two arguments

Posted: Tue Aug 25, 2020 9:36 am
by Robert
Permitting the expression

Code: Select all

MAX(INTEGER, 0)
looks like an error to me, and should be treated as a compiler bug.

I have not followed this discussion very closely, so have two questions:
1 - Do the proposed changes to DevCPB fully resolve this issue?
2 - Is the problem with characters the same issue, or a separate bug?

Re: MAX with two arguments

Posted: Tue Aug 25, 2020 11:05 pm
by cfbsoftware
Do the same issues apply to the MIN function? If they do then any possible rework to MAX should be considered for MIN as well. If they don't then it is likely that similar code patterns for MIN could be used.

There are a significant number of variations of valid / invalid parameter combinations for these two functions. The risk of introducing new problems with any modifications must be considered and extensive test cases developed to ensure that this has not happened. The original problem reported only occurs when attempts are made to compile badly written code that is unlikely to occur in real life. I would not want to see new problems introduced that affect correctly written code.

Re: MAX with two arguments

Posted: Wed Aug 26, 2020 10:56 am
by luowy
in my opinion,it is a bug, the compiler needs to be fixed;

accoding language report 10.3 as Zinn point out

Code: Select all

The following table lists the predeclared procedures. Some are generic procedures, i.e., they apply to several types of operands. v stands for a variable, x and y for expressions, and T for a type. The first matching line gives the correct result type.
the MAX(T) and MAX(x, y) is clearly explained that the two parameters are expression, not a type;


this issue apply to the MIN funtion also;

the bug at DevCPB.StPar1:

Code: Select all

| minfn: (*MIN*)
			IF p.hint # 1 (*p.class # Ntype*) THEN Op(min, p, x) ELSE err(64) END
| maxfn: (*MAX*)
			IF p.hint # 1 (*p.class # Ntype*) THEN Op(max, p, x) ELSE err(64) END
when the first parameter is a type, the "p.class" will be "Nconst" instead of "Ntype", so use "p.hint = 1" to check it ;

a simple test

Code: Select all

MODULE ObxMAX;

	IMPORT Log:=StdLog;
	
	
	PROCEDURE Do();
		VAR x,y:INTEGER;b:BOOLEAN;
	BEGIN
		(* invalid*)
		x := MAX(INTEGER, 0);
		x := MAX(INTEGER, y);
		
		x := MAX(0, INTEGER);
		x := MAX(y, INTEGER);
		
		x := MIN(INTEGER, 0);
		x := MIN(INTEGER, y);
		x := MIN(0, INTEGER);
		x := MIN(y, INTEGER);
		
		(*valid*)
		x := MAX(INTEGER);
		x := MAX(x, 0);
		x := MAX(x, y);
		 
		x := MIN(INTEGER);
		x := MIN(x, 0);
		x := MIN(x, y);
	END Do;


END ObxMAX.

Re: MAX with two arguments

Posted: Wed Aug 26, 2020 4:54 pm
by adimetrius
I like luowy's suggested fix better than my own, although they achieve the same result.

What about Zorko's post? He pointed out a situation when MAX/MIN is applied to two constants, which is fully evaluated at compile time, and that's done in a different procedure.

Re: MAX with two arguments

Posted: Thu Sep 03, 2020 7:10 am
by Josef Templ
There is yet another little bug in the docu of MIN/MAX(T), I think:

Code: Select all

MAX(T)	T = basic type	T	      maximum value of type T
	      T = SET	       INTEGER	maximum element of a set
The order is wrong.
SET must be first according to the rule that the first matching line defines the result because SET is a basic type.

- Josef