Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2010-01

Generics problem/question

16 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Honza

Hi all,

I tried to specialize fgl.TFPGList with some record type and got a compiler error.
Am I doing something completely wrong (sorry in that case) or is this a bug? (Ubuntu 9.10, 64 bit)

----

22:35  cat project1.pas
program project1;
{$mode objfpc}{$H+}
uses
	fgl;
type
  TPar = record
    I: Integer;
  end;
  TSpec = specialize TFPGList<TPar>;
begin
end.

22:35 fpc project1.pas
Free Pascal Compiler version 2.5.1 [2010/01/05] for x86_64 Copyright (c) 1993-2009 by Florian Klaempfl
Target OS: Linux for x86-64
Compiling project1.pas
Error: Operator is not overloaded
project1.pas(18) Fatal: There were 1 errors compiling module, stopping Fatal: Compilation aborted
Error: /home/myname/lib/fpc/2.5.1/ppcx64 returned an error exitcode (normal if you did not specify a source file to be compiled) 22:35 svn info ~/svn/fpc/trunk/
Path: /home/myname/svn/fpc/trunk
URL: http://svn2.freepascal.org/svn/fpc/trunk
Repository Root: http://svn2.freepascal.org/svn/fpc Repository UUID: 3ad0048d-3df7-0310-abae-a5850022a9f2 Revision: 14549
Node Kind: directory
Schedule: normal
Last Changed Author: jonas
Last Changed Rev: 14549
Last Changed Date: 2010-01-05 20:53:43 +0100 (Út, 05 led 2010)

22:35

----

Thanks in advance for any info.

bflm

Reply by email

leledumbo
to Honza

The error message needs to be extended for generics type.

Inside TFPGList in implementation section, there are some comparisons done with relational operators (I forgot what they are, just open fgl.pp). You need to overload those operators for your record type. Surely, the compiler wouldn't know how to compare 2 TPar without the overloading.

View this message in context: http://old.nabble.com/Generics-problem-question-tp27036004p27056130.html Sent from the Free Pascal - General mailing list .

Reply by email

Marco van de Voort
to leledumbo

In our previous episode, leledumbo said:

Show quoted text 5 lines
Inside TFPGList in implementation section, there are some comparisons done with relational operators (I forgot what they are, just open fgl.pp). You need to overload those operators for your record type. Surely, the compiler wouldn't know how to compare 2 TPar without the overloading.

I tried that, but it didn't work (defined > = < )

Reply by email

Marco van de Voort
to leledumbo: The error message needs to be extended for generics type. Inside TFPGList in…

In our previous episode, leledumbo said:

Inside TFPGList in implementation section, there are some comparisons done with relational operators (I forgot what they are, just open fgl.pp). You need to overload those operators for your record type. Surely, the compiler wouldn't know how to compare 2 TPar without the overloading.

One of the problems is the limited information in the errormsg (what operator is missing in what line)

Reply by email

leledumbo
to leledumbo

Sorry, I guess I was wrong. The specialization in my program uses a class instead of a record, the = operator is defined for a record but isn't used at all. I'm not sure where the problem is, only records and static arrays causes it.

One solution is to declare a pointer type to your record and specialize TFPGList with it.

View this message in context: http://old.nabble.com/Generics-problem-question-tp27036004p27070857.html Sent from the Free Pascal - General mailing list .

Reply by email

Honza

Hi all.

At Mantis Florian already explained, why it is not possible to provide more information in the error message. Still he meanwhile managed to make it better. I got some time to return to this and now I'm here:

17:11  cat project1.pas
program project1;
{$mode objfpc}{$H+}
uses
	fgl;
type
  TPar = record
    I: Integer;
  end;
operator = (A, B: TPar): Boolean;
begin
	Result := A.I = B.I;
end;
type
  TSpec = specialize TFPGList<TPar>;
begin
end.

17:22 fpc project1.pas
Free Pascal Compiler version 2.5.1 [2010/01/14] for x86_64 Copyright (c) 1993-2009 by Florian Klaempfl
Target OS: Linux for x86-64
Compiling project1.pas
Error: Operator is not overloaded: "<record type>" = "<record type>" project1.pas(24) Fatal: There were 1 errors compiling module, stopping Fatal: Compilation aborted
Error: /home/myname/lib/fpc/2.5.1/ppcx64 returned an error exitcode (normal if you did not specify a source file to be compiled) 17:22 svn info ~/svn/fpc/trunk
Path: /home/myname/svn/fpc/trunk
URL: http://svn2.freepascal.org/svn/fpc/trunk
Repository Root: http://svn2.freepascal.org/svn/fpc Repository UUID: 3ad0048d-3df7-0310-abae-a5850022a9f2 Revision: 14633
Node Kind: directory
Schedule: normal
Last Changed Author: paul
Last Changed Rev: 14633
Last Changed Date: 2010-01-14 09:41:27 +0100 (Čt, 14 led 2010)

17:23

I'm now able to track the source of the error message to line 715:50 of rtl/objpas/fgl.pp:

711  function TFPGList.IndexOf(const Item: T): Integer;
712  begin
713    Result := 0;
714    {$info TODO: fix inlining to work! InternalItems[Result]^}
715    while (Result < FCount) and (PT(FList)[Result]  Item) do
716      Inc(Result);
717    if Result = FCount then
718      Result := -1;
719  end;

Still I'm stuck and don't know how to use items like TPar in the specialization of TFPGList - or if it is a compiler bug.

Thanks in advance for anyone's help/explanation/hint.

-bflm

Topic/previous messages context:

Mantis issue:
http://bugs.freepascal.org/view.php?id=15480

Reply by email

leledumbo
to Honza

Ah... I can see it now:

711  function TFPGList.IndexOf(const Item: T): Integer;
712  begin
713    Result := 0;
714    {$info TODO: fix inlining to work! InternalItems[Result]^}
715    while (Result < FCount) and (PT(FList)[Result]  Item) do
716      Inc(Result);
717    if Result = FCount then
718      Result := -1;
719  end;

This is where the = operator is required ( is derived from = ).

I continue the discussion in mantis, so that this can be solved (hopefully).

View this message in context: http://old.nabble.com/Generics-problem-question-tp27036004p27173345.html Sent from the Free Pascal - General mailing list .

Reply by email

Aleksa Todorovic
to leledumbo
leledumbo wrote 16 lines
Ah... I can see it now: 711  function TFPGList.IndexOf(const Item: T): Integer; 712  begin 713    Result := 0; 714    {$info TODO: fix inlining to work! InternalItems[Result]^} 715    while (Result < FCount) and (PT(FList)[Result] Item) do 716      Inc(Result); 717    if Result = FCount then 718      Result := -1; 719  end; This is where the = operator is required ( is derived from = ). I continue the discussion in mantis, so that this can be solved (hopefully).

I've attached patch to mantis bug which makes compiler print error about missing operator "TPar" = "TPar". This could, at least, give user some hint about what is wrong.

The proper solution for this problem is not simple. Somehow, you will have to make operator = (const A, B: TPar) visible inside FGL unit (because of the way generics are currently implemented), or make compiler think that TPGList is implemented in the place where specialization occurs (so compiler first searches "specialization space", and after that "generic-declaration space").

Reply by email

Aleksa Todorovic
to Aleksa Todorovic
Aleksa Todorovic wrote 8 lines
The proper solution for this problem is not simple. Somehow, you will have to make operator = (const A, B: TPar) visible inside FGL unit (because of the way generics are currently implemented), or make compiler think that TPGList is implemented in the place where specialization occurs (so compiler first searches "specialization space", and after that "generic-declaration space").

One (not very nice) way to have generic list of records is using macros. I've extracted definition of TFPGList, made it ordinary type, and did some search/replace, so I get:

type
  _TFPGList_Type_ = class(TFPSList)
  type public
    TCompareFunc = function(const Item1, Item2: _TFPGList_ItemType_): Integer;
    TTypeList = array[0..MaxGListSize] of _TFPGList_ItemType_;
    PTypeList = ^TTypeList;
    PT = ^_TFPGList_ItemType_;
  [original code from FGL unit goes here]
  end;
constructor _TFPGList_Type_.Create;
begin
[...]
end;

[...]

Now, you insert code like this:

type
  TPar = record
    I: Integer;
  end;
operator = (const A, B: TPar): Boolean;
begin
  Result := (A.I = B.I);
end;
{$MACRO ON}
{$DEFINE _TFPGList_Type_ := TParList}
{$DEFINE _TFPGList_ItemType_ := TPar}
{$INCLUDE fpglist.inc}
{$MACRO OFF}

And you get list of TPar records!

Now, The Question is: should "specialize" construct also search symbols defined in the place where specialization occurs, not just those defined in the place where generic type is defined?

On the other hand, the only problem so far (regarding this matter) is operator = on records. Maybe there should be special rule for this situation?

Reply by email

Aleksa Todorovic
to Aleksa Todorovic
Aleksa Todorovic wrote 8 lines
On Mon, Jan 18, 2010 at 04:07, Aleksa Todorovic wrote: One (not very nice) way to have generic list of records is using macros. I've extracted definition of TFPGList, made it ordinary type, and did some search/replace, so I get: [SNIP]

Just to report how I managed to (ab)use FPC and Lazarus to have both generics of records and full code-completition (note I turned C-style macros on for the whole project):

in interface:

  TMessageParameter = record
    ...
  end;
  TMessageParameters = TList; // this makes Lazarus code completition
actually work; maybe better to use TFPSList
operator = (const A, B: TMessageParameter): Boolean;
{$DEFINE _TFPGList_Type_ := TMessageParametersFPGList}
{$DEFINE _TFPGList_ItemType_ := TMessageParameter}
{$INCLUDE fpglist_h.inc} // copied and adapted interface from FGL
{$DEFINE TMessageParameters := TMessageParametersFPGList}
// last line is used to make it all actually work

in implementation:

operator = (const A, B: TMessageParameter): Boolean;
begin
  Result := ...;
end;
{$DEFINE _TFPGList_Type_ := TMessageParametersFPGList}
{$DEFINE _TFPGList_ItemType_ := TMessageParameter}
{$INCLUDE fpglist.inc} // copied and adapted implementation from FGL

Reply by email

Gerhard Scholz
to Honza: I tried to specialize fgl.TFPGList with some record type and got a compiler error. Am I…

Some lines are ignored.

An IF-clause is ignored.

Versin 2.2.4 runs o.k.!!!!

The program:

program rangtest ;
  type
    trange = 0..2030 ;
    ytrange = 1990..2030 ;
  CONST
    lrange =   low ( trange ) ;
    hrange =  high ( trange ) ;
    ylrange =  low ( ytrange ) ;
    yhrange = high ( ytrange ) ;
  var
    bbb : trange ;
    kkk : longint ;
    xyzzy : array [ ytrange, 1..100 ] of
              record
                xyzp : longint ;
                xyzb : boolean ;
               end ;
  begin       (*$r+,s+,o+*)
    bbb := 0 ;
    kkk := 1 ;
    IF ( bbb >= ylrange )                   //  this IFstatement can not be
found in the assembler file
       AND ( bbb <= yhrange )         //  and the program stops with range
error
      THEN begin                             //
        WITH xyzzy[bbb,kkk] DO
          BEGIN
            xyzp := 2 ;
            xyzb := True ;
           END ;
       end
      else writeln ( 'out' ) ;
   end.

OS: WinXP

Output of the compiler:

Free Pascal Compiler version 2.4.0 [2009/12/18] for i386 Copyright (c) 1993-2009 by Florian Klaempfl
Note: Switching assembler to default source writing assembler Target OS: Win32 for i386
Compiling rangtest.pas
rangtest.pas(34,12) Warning: unreachable code
rangtest.pas(16,5) Note: Local variable "xyzzy" is assigned but never used Assembling rangtest
Linking .\rangtest.exe
35 lines compiled, 0.1 sec , 35952 bytes code, 1728 bytes data 1 warning(s) issued
2 note(s) issued
1 Datei(en) kopiert.
1 Datei(en) kopiert.

the assembler file (only the part from BEGIN to WITH)

# [rangtest.pas]
# [22] begin (*$r+,s+,o+*)
call FPC_INITIALIZEUNITS
# Register eax,ecx,edx released
# Register ax allocated
.stabn 68,0,22,.Ll2 - _main
.Ll2:
movw $0,%ax
# Register eax allocated
movl $0,%eax
# Register eax released
# Register dx allocated
.stabn 68,0,23,.Ll3 - _main
.Ll3:
# [23] bbb := 0 ;
movw $0,%dx
# Register ecx allocated
.stabn 68,0,24,.Ll4 - _main
.Ll4:
# [24] kkk := 1 ;
movl $1,%ecx
# Register eax allocated
.stabn 68,0,28,.Ll5 - _main

##
## Here should be some result of the IF !!!!! the 2.2.4 version does not drop these lines
##

.Ll5:
# [28] WITH xyzzy[bbb,kkk] DO
movzwl %dx,%eax
subl $1990,%eax
cmpl $40,%eax
# Register eax released
jbe .Lj9
call FPC_RANGEERROR
.Lj9:

Reply by email

Gerhard Scholz
to Jonas Maebe

Thanks.

I tried to report via the bugs , but I didn't find the link to enter a fresh bug; maybe I just didn't see it.

Gerhard

Earlier message 24 lines
----- Original Message ----- From: "Jonas Maebe" To: "FPC-Pascal users discussions" Sent: Friday, February 12, 2010 7:13 PM Subject: Re: [fpc-pascal] 2.4.0: Some lines are not compiled (just thrown away) On 24 Jan 2010, at 21:10, Gerhard Scholz wrote: > Some lines are ignored. > > An IF-clause is ignored. > > Versin 2.2.4 runs o.k.!!!! Fixed. Please report bugs at http://bugs.freepascal.org in the future so they can't be forgotten. Jonas_______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Jonas Maebe
to Gerhard Scholz
Gerhard Scholz wrote
I tried to report via the bugs , but I didn't find the link to enter a fresh bug; maybe I just didn't see it.

You first have to create an account and log in. Only then the "Report Issue" link becomes available.

Jonas

Reply by email