MAX with two arguments

User avatar
Ivan Denisov
Posts: 362
Joined: Tue Sep 17, 2013 12:21 am
Location: Krasnoyarsk, Russia

MAX with two arguments

Post by Ivan Denisov »

Oleg found

Code: Select all

MODULE TestCP;

CONST
  max* = MAX(INTEGER, 0);

END TestCP.
This invalid code gives not error.
User avatar
adimetrius
Posts: 68
Joined: Sun Aug 04, 2019 1:02 pm

Re: MAX with two arguments

Post 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.
Zorko
Posts: 26
Joined: Tue Sep 17, 2013 10:13 pm
Location: Ukraine
Contact:

Re: MAX with two arguments

Post 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
Zinn
Posts: 123
Joined: Mon Nov 24, 2014 10:47 am
Location: Frankfurt am Main
Contact:

Re: MAX with two arguments

Post 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
User avatar
adimetrius
Posts: 68
Joined: Sun Aug 04, 2019 1:02 pm

Re: MAX with two arguments

Post 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.
User avatar
Robert
Posts: 177
Joined: Sat Sep 28, 2013 11:04 am
Location: Edinburgh, Scotland

Re: MAX with two arguments

Post 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?
cfbsoftware
Posts: 55
Joined: Wed Sep 18, 2013 10:06 pm
Contact:

Re: MAX with two arguments

Post 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.
luowy
Posts: 87
Joined: Thu Dec 17, 2015 1:32 pm

Re: MAX with two arguments

Post 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.
User avatar
adimetrius
Posts: 68
Joined: Sun Aug 04, 2019 1:02 pm

Re: MAX with two arguments

Post 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.
Josef Templ
Posts: 262
Joined: Tue Sep 17, 2013 6:50 am

Re: MAX with two arguments

Post 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
Post Reply