Page 2 of 5

Re: IN function with SETs

Posted: Sat Jun 06, 2015 8:13 am
by Zinn
Thanks Luowy,

I will add you prefered version to the next CPC edition

Helmut

Re: IN function with SETs

Posted: Sat Jun 06, 2015 8:17 am
by cfbsoftware
Robert wrote:The language report says
x IN s stands for "x is an element of s". x must be an integer in the range 0..MAX(SET), and s of type SET.
I wonder why they made that change in the transition from Oberon to Component Pascal? The Oberon / Oberon-2 / Oberon-07 Language Reports are all less restrictive:
x IN s stands for "x is an element of s". x must be of type INTEGER, and s of type SET.
When using Oberon I sometimes find it convenient to write code like this:

Code: Select all

IF i IN {0..9} THEN ...
rather than

Code: Select all

IF (i >= 0) and (i <= 9) THEN ...
and would be disappointed if it didn't work or trapped on some values of i.

Re: IN function with SETs

Posted: Sat Jun 06, 2015 10:45 am
by Robert
There seems to be a growing consensus that the two code fragments

Code: Select all

IF k IN {0..9} THEN ...
IF (k >= 0) and (k <= 9) THEN ...
should behave the same, and I would be quite happy with that.

- If we made this change how/where would it be documented?
I think it is compatible with the current language report, which could be interpreted as saying that out of range k is undefined, so FALSE is a permitted result.
Would we consider changing the report back to the Oberon wording to make this clearer?

- Iuowy: Does your second suggested change implement this for VARiable k? Does it implement this for CONSTant k?
Does your suggested change make the run-time code slower?

Re: IN function with SETs

Posted: Sat Jun 06, 2015 12:16 pm
by cfbsoftware
luowy wrote:which one is better?
None. They are not backward-compatible. The programmer no longer has the ability to skip the runtime checks if that is preferred.

Re: IN function with SETs

Posted: Sat Jun 06, 2015 3:25 pm
by luowy
Robert wrote:Does your second suggested change implement this for VARiable k? Does it implement this for CONSTant k?
Does your suggested change make the run-time code slower?
Hi Robert,
1, k is variable! const mode has checked at compile time already.we only need fixup variable mode.
2, only 5 bytes added,
from

Code: Select all

 
0F A3 45 F8 	BT	[EBP-8], EAX	
0F 92 C0 	SETB	AL
to

Code: Select all

83 F8 20 	CMP	EAX, 32	;<<<
73 04 	JNB	4              ;<<<
0F A3 45 F8 	BT	[EBP-8], EAX	
0F 92 C0 	SETB	AL
cfbsoftware wrote:None. They are not backward-compatible. The programmer no longer has the ability to skip the runtime checks if that is preferred.
hi Chris,please check the "BT" code desc(in the intel manual part2) carefully:
when k is a variable,the emited code like this:

Code: Select all

BT  [EBP-8], EAX	
SETB	AL
if the k(EAX) is beyond 31, will check the word at memory [EBP-8+ k div 32] ;
thought the BT is valid, but the result depend on the wrong memory word.
that is not we want. if you do a check:

Code: Select all

	PROCEDURE Set*();	
		VAR k: INTEGER;
		VAR s: ARRAY 2 OF SET;
		VAR b: BOOLEAN;
	BEGIN
		k := 32;     
		s[0] := {0..31};
		s[1] := {0..31};
		Log.Bool(k IN s[0]); Log.Ln;
		s[1] := {1..31};
		Log.Bool(k IN s[0]); Log.Ln;
	END Set;
you will understand why we need this fixup;if you have any unbackward-compatible source code,please let we know.

luowy

Re: IN function with SETs

Posted: Sun Jun 07, 2015 7:55 am
by Robert
luowy wrote:If you do a check: ... you will understand why we need this fixup.luowy

Code: Select all

      k := 32;     
      s[0] := {0..31};
      s[1] := {0..31};
      f.BoolLn (k IN s[0]);
      s[1] := {1..31};
      f.BoolLn (k IN s[0]);

 new symbol file   116   4
 TRUE 
 FALSE
One can discuss if the current behaviour complies with the Component Pascal Language Report, but I think we should treat it is a bug, and fix it.

One can write some code (eg , k IN s[0])) test it, find it ok but five minutes later it behaves differently. This could lead to impossible to debug problems; even a random number generator does not behave like this.

I vote for iuowy's second suggestion.

Re: IN function with SETs

Posted: Sun Jun 07, 2015 8:52 am
by Zinn
I create a new version of CPC edition (RC6 - Built 45) with Louwy's 2nd solution. You can download it for testing at

http://www.zinnamturm.eu/pac/B2015.0607.zip

and its change protocol

http://www.zinnamturm.eu/pac/B2015.0607.txt

Please test it and report the result.

Re: IN function with SETs

Posted: Sun Jun 07, 2015 9:43 am
by Ivan Denisov

Re: IN function with SETs

Posted: Mon Jun 08, 2015 9:23 pm
by Robert
I have received the following observations from Oleg N. Cher
Dear Robert,

It may be that for argument >= 32 the result of such operation will be
undefined. I'm surprised too. But if you rewrite the code at this manner:

BEGIN
RETURN 33 IN {1}

You will have error "set element greater than MAX(SET) or less than 0".

So BlackBox validates arguments at compile time, but does not at
runtilme. I think, teason of it is improvement of the performance.


Btw, Ofront gives the same error at compile time and the same result of
work in runtime:

static INTEGER Test_k;

static BOOLEAN Test_Fn (void)
{
Test_k = 33;
return __IN(Test_k, 0x02);
}

where macros __IN defined as:

#define __IN(x, s) (((s)>>(x))&1)

So result = (2>>33)&1 = NOT ZERO = TRUE ( Why? )

Tested in MINGW and TCC. As I understand, (2>>33)&1 must be = 0 in 32
bit depth range, but maybe this expression calculated also in
compile-time with bigger bit depth?

Who can say how works BlackBox's IN operation at low-level?

Re: IN function with SETs

Posted: Tue Jun 09, 2015 4:40 am
by Josef Templ
This is not a bug. Leave it as it is.

It is obvious that the runtime range checks are avoided by default in order to improve performance.
The behavior of using MOD 32 follows from the underlying Intel i386 architecture
and is not a surprise; it is the simplest thing a 32 bit CPU can do.

The proposed fix of returning FALSE is pure nonsense.
Please start thinking before programming.

- Josef