Consider the following test program.
program test;
type Str255 = record sLength: Byte; sChars: packed array[1..255] of Char end;
operator + ( protected var s1, s2: Str255 ) = theResult : Str255; var len1, len2: Integer; begin len1 := s1.sLength; len2 := Min( 255 - len1, s2.sLength); theResult.sLength := len1 + len2; if len1 > 0 then theResult.sChars[1..len1] := s1.sChars[1..len1]; if len2 > 0 then theResult.sChars[len1+1..len1+len2] := s2.sChars[1..len2]; end;
var s1: Str255 value ( sLength: 1, sChars: 'A'); s2: Str255 value ( sLength: 1, sChars: 'B'); s3: Str255 value ( sLength: 1, sChars: 'C'); s4: Str255;
begin s4:=s1+s2+s3 { Error: reference expected, value given }; writeln( s4.sChars[ 1..s4.sLength]) end.
The program triggers an error for s1+s2+s3. The error doesn't occur when the expression has only one + operator (e.g. s1+s2). The problem disappears when using const parameters. It looks like the internal representation of an intermediate result is triggering the compiler error !
Regards,
Adriaan van Os
On Thu, Oct 27, 2005 at 09:54:10PM +0200, Adriaan van Os wrote:
Consider the following test program.
program test;
type Str255 = record sLength: Byte; sChars: packed array[1..255] of Char end;
operator + ( protected var s1, s2: Str255 ) = theResult : Str255; var len1, len2: Integer; begin len1 := s1.sLength; len2 := Min( 255 - len1, s2.sLength); theResult.sLength := len1 + len2; if len1 > 0 then theResult.sChars[1..len1] := s1.sChars[1..len1]; if len2 > 0 then theResult.sChars[len1+1..len1+len2] := s2.sChars[1..len2]; end;
var s1: Str255 value ( sLength: 1, sChars: 'A'); s2: Str255 value ( sLength: 1, sChars: 'B'); s3: Str255 value ( sLength: 1, sChars: 'C'); s4: Str255;
begin s4:=s1+s2+s3 { Error: reference expected, value given }; writeln( s4.sChars[ 1..s4.sLength]) end.
The program triggers an error for s1+s2+s3. The error doesn't occur when the expression has only one + operator (e.g. s1+s2). The problem disappears when using const parameters. It looks like the internal representation of an intermediate result is triggering the compiler error !
Regards,
Adriaan van Os
This has nothing to do with internal representation, it's just the usual Pascal syntax rules. If a function (or operator) has a var parameter, you should feed it a reference. Variables s1 and s2 are references, thus s1+s2 is OK. The expression s1+s2 itself is not a reference, thus (s1+s2)+s3 is invalid. Const parameters are syntactically value parameters (though they are implemented as call by reference), thus these restrictions do not apply to them.
Emil Jerabek
At 22:34 +0200 27/10/05, Emil Jerabek wrote:
Const parameters are syntactically value parameters (though they are implemented as call by reference), thus these restrictions do not apply to them.
Const parameters are not necessarily passed by reference, they may be passed by either reference or value.
Generally, it is accepted that const parameters are passed by reference unless the parameter is "small" for some definition of the word "small", often SizeOf(parameter) <= SizeOf(Pointer) and often somewhat dependent on the structure of the parameter (eg array[1..SizeOf(Pointer)] might be treated differently))
Currently, GPC has a "bug" in that const s: String255 or const s: TString or any fixed size string is passed by value. Generally, there is no need to specify a fixed string size, and these can all be changed to const s: String which is indeed passed by reference, and the reason this "bug" was not detected (recently I went through my entire code base changing all such occurrences after I determined that this "bug" was the cause of very serious performance issues (some critical routines were taking one hundred times longer than expected). I use quotes around "bug" because it is not a violation of the specification for const, which does not define the implementation at all.
For compatibility with C interfaces of the form const *x, as well as to enforce the implementation as "by reference" regardless of the compiler's thoughts on "small", it is intended to implement "const var" parameters which are read only parameters, passed by reference, but which do not have the strict restrictions of "protected var", so that cases like Adriaan's + operator would work and guarantee to pass by reference.
I'm not aware of a time frame for either "const var" or "const s: TString".
Enjoy, Peter.