Re: [fpc-pascal] Floating point question

2024-02-22 Thread Thomas Kurz via fpc-pascal
> For constants, the compiler will choose a type and consequently the 
> precision. 
> Jonas and others have explained the rules that the compiler uses.
>
> If you don't like the rules that the compiler uses, you can set a type for 
> your
> constants. When you explicitly set a type, you are also specifying the 
> precision of the > calculation.

If the ruleset won't change - and from what I've read from the developers, it 
won't change - could we please have the compiler issue a warning (or a hint) if 
a loss in precision happens.

E.g. "Warning: constant reduced to single precision. Use {$MINFPCONSTPREC} or 
Double() to keep full precision."

I am aware about this behavior now, but nevertheless I'd like to get warned if 
I forget about either of those.

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Floating point question

2024-02-22 Thread Thomas Kurz via fpc-pascal
Aaaah, ok. Thank you very much for alrifying this long-standing question!


- Original Message - 
From: Tomas Hajny via fpc-pascal 
To: FPC-Pascal users discussions 
Sent: Thursday, February 22, 2024, 15:25:34
Subject: [fpc-pascal] Floating point question

On 2024-02-22 15:08, Thomas Kurz via fpc-pascal wrote:
>> If you're using Win64, then the answer is simple: x86_64-win64 unlike 
>> any
>> other x86 target does not support Extended, so neither the compiler 
>> nor the
>> code in runtime will ever calculate anything with that precision.

> That's another thing I've never understood. How can it depend on the
> OS? It's the CPU which does math, and I don't understand what the OS
> has to do with that? If amd64 architecture didn't support the
> extended-type at all, I'd say "ok". But it's supported on Linux but
> not on Windows? Huh?

The reason is that the operating system is among others responsible for 
controlling the multitasking. That includes saving the context of the 
originally active task and restoring the context of the new task to the 
original state before it was interrupted. If Win64 doesn't guarantee 
restoring FPU registers specific to the extended type, using this type 
would get you into troubles despite its support in the FPU.

Tomas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Floating point question

2024-02-22 Thread Thomas Kurz via fpc-pascal
> for example, here on Earth, (7 decimal places) 0.001 degree latitude is 
> ""only"" 1cm... (8 decimal places) 0.0001 degree latitude is ""only"" 
> 1mm... 
> longitude, on the other hand, is variable such that 7 decimal places at the 
> equator is the same as latitude but as you move toward the poles, it changes 
> such that 4 decimal places is 20cm...

My initial problem (i.e. why I asked the original question -- which I do regret 
meanwhile *g*) was that we do use floating-point numbers for date and time 
operations. (TDateTime = Double)

And I had discrepancies of about 40 seconds when converting between 
astronomical dates and TDateTime. This was how it all started...

We need approx. 5 decimals to represent one second (because the non-fractional 
part is considered being the day number). So "single" precision isn't 
acceptable here. If TDateTime were Unix-timestamp, it wouldn't matter. But 
since TDateTime is Julian day number (maybe with an offset, but that's 
irrelevant here), it unfortunately does matter.

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Floating point question

2024-02-22 Thread Thomas Kurz via fpc-pascal
> If you're using Win64, then the answer is simple: x86_64-win64 unlike any
> other x86 target does not support Extended, so neither the compiler nor the
> code in runtime will ever calculate anything with that precision.

That's another thing I've never understood. How can it depend on the OS? It's 
the CPU which does math, and I don't understand what the OS has to do with 
that? If amd64 architecture didn't support the extended-type at all, I'd say 
"ok". But it's supported on Linux but not on Windows? Huh?

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Floating point question

2024-02-13 Thread Thomas Kurz via fpc-pascal
> But, sorry, because we are talking about compile time math, performance 
(nanoseconds) in this case doesn't count, IMO.

That's what i thought at first, too. But then I started thinking about how to 
deal with it and sumbled upon difficulties very soon:

a) 8427.0 + 33.0 / 1440.0
An easy case: all constants, so do the calculation at highest precision and 
reduce it afterwards, if possible.

b) var_single + 33.0 / 1440.0
Should also be feasable by evaluating the constant expression first, then 
reducing it to single (if possible) and adding the variable in the end.

c) 8427.0 + var_double / 1440.0
Because of using the double-type variable here, constants should be treated as 
double even at the cost of performance due to not knowing whether the result 
will be assigned to a single or double.

d) 8427.0 + var_single / 1440.0
And this is the one I got to struggle with. And I can imagine this is the 
reason for the decision about how to handle decimal constants.
My first approach would have been to implicitly use single precision values 
throughout the expression. This would mean to lose precision if the result will 
be assigned to a double-precision variable. One could say: "bad luck - if the 
programmer intended to get better precision, he should have used a 
double-precision variable as in case c". But this wouldn't be any better than 
the current state we have now.

Overall, I must admit that the choice ain't easy at all.

In this situation, it might be a good choice to ask "what would other languages 
do here?". As far as I know about C, it treats constants as double-precision by 
default. You have to write "1.0f" if you explicitly want single precision.
But I think it's too late for introducing yet another change. Imho, the correct 
decision at FPC v2.2 would have been to keep the previous behavior and instruct 
those concering performance to use "{$MINFPCONSTPREC 32}" (or using the "1.0f" 
notation) instead of requiring everyone to use "{$MINFPCONSTPREC 64}" to keep 
compatibility with previous releases.

Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Floating point question

2024-02-12 Thread Thomas Kurz via fpc-pascal
>> You cannot do this in Pascal. The evaluation of the expression on the 
>> right of := does not
>> know (and should not know) what the type is of the expression on the left.

> It's even theoretically impossible to do in case the result is passed to 
> a function or intrinsic that is overloaded with single/double/extended 
> parameters.

In other cases, I got a "can't determine which overloaded function to call" 
error, so I think this should be handable; but I understand the first argument 
of course.

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Floating point question

2024-02-12 Thread Thomas Kurz via fpc-pascal
I wouldn't say so. Or at least, not generally. Why can't the compiler do what 
the programer intends to do:

var
  s: single;
  d: double;
  e: extended;
  
begin
  s := 8427.0 + 33.0 / 1440.0; // treat all constants all "single"
  d := 8427.0 + 33.0 / 1440.0; // treat all constants all "double"
  e := 8427.0 + 33.0 / 1440.0; // treat all constants all "extended"
end.

Shouldn't this satisfy all the needs? Those caring for precision will work with 
double precision and don't have to take care for a loss in precision. Those 
caring for speed can use the single precision type and be sure that no costly 
conversion to double or extended will take place.




- Original Message - 
From: Jonas Maebe via fpc-pascal 
To: fpc-pascal@lists.freepascal.org 
Sent: Sunday, February 11, 2024, 23:29:42
Subject: [fpc-pascal] Floating point question

On 11/02/2024 23:21, Bernd Oppolzer via fpc-pascal wrote:
> and this would IMHO be the solution which is the easiest to document and 
> maybe to implement
> and which would satisfy the users.

And generate the slowest code possible on most platforms.


Jonas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] "Unexpected end of file" when having an open comment after the final "end."

2024-02-08 Thread Thomas Kurz via fpc-pascal
Hello Martin,

I've been using Pascal for more than 30 years now, but I must admit I've never 
before seen the construct you posted.

And it doesn't compile either:

project1.lpr(4,4) Error: Syntax error, "." expected but ";" found

Kind regards,
Thomas


- Original Message - 
From: Martin Wynne via fpc-pascal 
To: fpc-pascal@lists.freepascal.org 
Sent: Thursday, February 8, 2024, 20:01:17
Subject: [fpc-pascal] "Unexpected end of file" when having an open comment 
after the final "end."

Hi Thomas,

The error is not the file content after "end.".

The error is not having the expected "end;" after "begin".

This works ok:

_

program test;

begin
end;

end.

abc 123

_

Martin.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] "Unexpected end of file" when having an open comment after the final "end."

2024-02-08 Thread Thomas Kurz via fpc-pascal
Hello all,

I'm unsure about whether or not to report this as a bug. Imho, it is a bug, but 
maybe there's a good reason to handle this.

Please take the following example:

---start---

program test;

begin
end.

{

---end---

Result:

Z:\>ppc386.exe testproj.pas
Free Pascal Compiler version 3.2.2 [2022/05/15] for i386
Copyright (c) 1993-2021 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling testproj.pas
testproj.pas(6,1) Fatal: Unexpected end of file
Fatal: Compilation aborted


I'd say the code should compile without any errors for the following reasons:

1. The "end." tells the compiler that the file is finished here. Whatever comes 
after this should not be considered by the compiler.
2. The compiler doesn't consider any other statement after "end.". For example, 
replacing the open comment with something like "vra" doesn't cause an error 
either.

Kind regards,
Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Floating point question

2024-02-06 Thread Thomas Kurz via fpc-pascal
I think the reason why this new behavior doesn't occur with 1440.1 is that this 
number cannot be reduced to "single" precision. It will keep "double" precision.

Consider this instead:

program TESTDBL1 ;

var TT : double ; EE: double;

begin (* HAUPTPROGRAMM *)
   TT := 8427 + 33 / 1440.5 ;
   EE := Double(8427) + Double(33) / Double(1440.5);
   WRITELN ( 'tt=' , TT : 20 : 20 ) ;
   WRITELN ( 'ee=' , EE : 20 : 20 ) ;
end (* HAUPTPROGRAMM *) .

Result:

tt=8427.022460937500
ee=8427.0229087122534000

So it's the same as with ".0". FPC treats the constant as type "single". Imho, 
this is perfectly legal, but when assigning an expression to a "double" 
variable, an implicit cast to double should occur.

When using a variable of type "single" (instead of a constant), this casting is 
done:

program TESTDBL1 ;

{$mode objfpc}

var TT : double ;
EE: double;
x: Single = 1440.5;

begin (* HAUPTPROGRAMM *)
   TT := 8427 + 33 / x ;
   EE := 8427 + 33 / Double(x);
   WRITELN ( 'tt=' , TT : 20 : 20 ) ;
   WRITELN ( 'ee=' , EE : 20 : 20 ) ;
end (* HAUPTPROGRAMM *) .

Prints:
tt=8427.0229087122534000
ee=8427.0229087122534000

I don't know whether this is intentional or not, but I cannot see any good 
reason why using a constant in an expression has to be treated differently than 
using a variable. To me as a programmer, this behavior is unexpected.

If the 2.2 change is not going to be reverted (and as far as I understand 
Florian correctly, it won't be changed), maybe one could at least introduce a 
warning about a loss of precision when using a constant of type "single" in an 
expression which will be assigned to a variable of type "double".

Kind regards,
Thomas




- Original Message - 
From: James Richters via fpc-pascal 
To: 'FPC-Pascal users discussions' 
Sent: Tuesday, February 6, 2024, 16:23:30
Subject: [fpc-pascal] Floating point question

What's apparently happening now is:
MyExtended := ReducePrecisionIfNoLossOfData (8246) +
ReducePrecisionIfNoLossOfData (33.0) / ReducePrecisionIfNoLossOfData
(1440.0);
But it is not being done correctly, the 1440.0 is not being reduced all the
way to an integer, because it was, everything would work.  The 1440.0 is
being considered a single, and the division is also being now considered a
single, even though that is incorrect.   But 1440.1 is not being considered
a single, because 1440.1 is not breaking everything.

What should be happening is:
MyExtended := ReducePrecisionIfNoLossOfData(8246+33.0/1440.0);


I just realized something...  regardless of when or how the reduction in
precision is happening, the bug is different than that,  because the result
of a byte divided by a single when stored in a double is a double, NOT a
single,  there should be no problem here, there is a definite bug. 

Consider this:
program TESTDBL1 ;

Const
   HH = 8427.02291667;
Var
   AA : Integer;
   BB : Byte;
   CC : Single;
   DD : Single;
   EE : Double;
   FF : Extended;
   GG : Extended;
   

begin
   AA := 8427;
   BB := 33;
   CC := 1440.0;
   DD := AA+BB/CC;
   EE := AA+BB/CC;
   FF := AA+BB/CC;
   GG := 8427+33/1440.0;
   
   WRITELN ( 'DD = ',DD: 20 : 20 ) ;
   WRITELN ( 'EE = ',FF: 20 : 20 ) ;
   WRITELN ( 'FF = ',FF: 20 : 20 ) ;
   WRITELN ( 'GG = ',GG: 20 : 20 ) ;
   WRITELN ( 'HH = ',HH: 20 : 20 ) ;
end.

When I do the division of a byte by a single and store it in an extended, I
get the division carried out as an extended.
FF, GG, and HH should all be exactly the same if there is not a bug.
But:

DD = 8427.02246100
EE = 8427.022916625000
FF = 8427.022916625000
GG = 8427.022460937500
HH = 8427.022916625000

GG,  the one with constants, is doing it wrong... 

If the entire formula was calculated the original way at full precision,
then only result was reduced if there was no loss in precision right before
storing as a constant,  then this solves the problems for everyone, and this
is the correct way to do this.  Then everyone is happy, no Delphi warnings,
no needlessly complex floating point computations if the result of all the
math is a byte, and no confusion as to why it works with 1440.1 and not
1440.0  Compatibility with all versions of Pascal,  etc..  

This calculation is only done once by the compiler, the calculation should
be done at full possible precision and only the result stored in a reduced
way if it makes sense to do so.

The problem I have with the changes made with v2.2, is that it's obvious
that the change was going to introduce a known bug at the time:
"Effect: some expressions, in particular divisions of integer values by
floating point constants, may now default to a lower precision than in the
past."
How is this acceptable or the default?? 

"Remedy: if more precision is required than the default, typecast the
floating point constant to a higher precision type, e.g. extended(2.0).
Alternatively, you can use the -CF command line option to change the default

Re: [fpc-pascal] Floating point question

2024-02-06 Thread Thomas Kurz via fpc-pascal
Well, this is funny because I *did* compile it on DOS with Turbo Pascal 5.5, 
and I got the correct result there. Cross-compiling with FPC to msdos target 
gave the "wrong" (aka unexpected) result again. There were so many factors 
involved which caused great confusion.

>From my point of view, an expression being an assigned to a variable of type 
>"double" should be evaluated with double precision, not single. This is 
>obviously the way integers are handled by internally using int64. A few weeks 
>ago, I had incosistent behavior between x64 and x86 modes and it turned out 
>that 32-bit code did internal castings to int64 thus resulting in the expected 
>value whereas 64-bit cannot cast to int128 (because there is no int128) and 
>thus gives an unexpected result (well, at least to me). So my intuition would 
>(and obviously did!) expect double precision throughout the calculation.

Kind regards,
Thomas



- Original Message - 
From: James Richters 
To: 'FPC-Pascal users discussions' 
Sent: Tuesday, February 6, 2024, 13:44:37
Subject: [fpc-pascal] Floating point question

I don't think you were doing anything wrong, that's what I am simply trying
to point out.  If you ran your code on Turbo Pascal 7.0, you would not have
an issue, it would be fine.  There is no reason for a programmer to expect
this behavior and it's very confusing when it does come up.

There is a bug here and it should be acknowledged instead of defended.
Discovering bugs is a good thing, it can lead to improvements to make the
system better for everyone, but only if the discovery is learned from and
acted upon.  I'm sure everyone here can relate to how frustrating it can be
to encounter a bug and have no idea whatsoever what the problem is.
Undiscovered bugs are much worse than those which have been figured out.  

I think this is one that can be very frustrating for a lot of people, and
it's very difficult to figure out what's happening,  because everything
happens correctly >99.9% of the time.  If you put anything from x.001 to
x.999 it has no problem, if you put x.0, you have a problem.  Put as many
decimals as you like to see why there is no reason why any programmer should
expect this behavior.   On top of that x has no problem, and many
programmers use x.0 when x would have been fine, they are just in the habit
of putting the .0 and in Turbo Pascal, there was never a problem with doing
this. 

I am glad we at least have an explanation, but how many others are going to
need to re-discover this issue that should not even be an issue?  
It can still be a problem for people who didn't happen to come across this.
I didn't expect it to be an issue.  While compiling with -CF64 or using
{$MINFPCONSTPREC 64}  fixes it for programs that use doubles, there is no
good solution I can find for programs that use extended, because you can't
put 80 into either of those.  So for extended programs the only solution I
can think of at the moment is to go through the WHOLE thing and replace all
the x.0's with x  Which I have started doing but it's a tedious chore. 

I appreciate the discussion here, because I had noticed inaccuracies from
time but I was never able to get far enough in to realize this is what was
happening.   It's very frustrating indeed and I think if something can be
done to save others this frustration and unexpected behavior, it would be
helpful.

James

-Original Message-----
From: fpc-pascal  On Behalf Of
Thomas Kurz via fpc-pascal
Sent: Tuesday, February 6, 2024 6:59 AM
To: 'FPC-Pascal users discussions' 
Cc: Thomas Kurz 
Subject: Re: [fpc-pascal] Floating point question

I'd like to apologize, because my intention hasn't been to raise controverse
discussions. I'm very thankful about the explanation. From the beginning, I
knew that the error was on my side, but I didn't know *what* I'm doing
wrong.

Again, thanks for helping.

Kind regards,
Thomas



- Original Message -
From: James Richters via fpc-pascal 
To: 'FPC-Pascal users discussions' 
Sent: Sunday, February 4, 2024, 18:25:39
Subject: [fpc-pascal] Floating point question

I agree with Aadrian 100%
 
"New behaviour: floating point constants are now considered to be of the
lowest precision which doesn't cause data loss"

We are getting data loss So it's doing it WRONG.

So we are all living with a stupid way of doing things so some Delphi code
won't have warnings?

Who came up with this???

The old way was CORRECT,   instead of changing it for everyone making it
wrong for most users, a compiler directive should have been needed to get
rid of the warnings, or ONLY applied in Mode Delphi.  Not to make everything
incorrect for everyone unless you add a directive. The problem with this
that no one is expecting to need to add a directive to do things right. 

Consider this:
 
Var
  MyVariable : Extended;

MyVariable := 8427 + 33 / 1440.0;

Since I am storing the result i

Re: [fpc-pascal] Floating point question

2024-02-06 Thread Thomas Kurz via fpc-pascal
I'd like to apologize, because my intention hasn't been to raise controverse 
discussions. I'm very thankful about the explanation. From the beginning, I 
knew that the error was on my side, but I didn't know *what* I'm doing wrong.

Again, thanks for helping.

Kind regards,
Thomas



- Original Message - 
From: James Richters via fpc-pascal 
To: 'FPC-Pascal users discussions' 
Sent: Sunday, February 4, 2024, 18:25:39
Subject: [fpc-pascal] Floating point question

I agree with Aadrian 100%
 
"New behaviour: floating point constants are now considered to be of the lowest 
precision which doesn't cause data loss"

We are getting data loss So it's doing it WRONG.

So we are all living with a stupid way of doing things so some Delphi code 
won't have warnings?

Who came up with this???

The old way was CORRECT,   instead of changing it for everyone making it wrong 
for most users, a compiler directive should have been needed to get rid of the 
warnings, or ONLY applied in Mode Delphi.  Not to make everything incorrect for 
everyone unless you add a directive. The problem with this that no one is 
expecting to need to add a directive to do things right. 

Consider this:
 
Var
  MyVariable : Extended;

MyVariable := 8427 + 33 / 1440.0;

Since I am storing the result in an Extended, I DO NOT EXPECT the 33/1440 to be 
a SINGLE, that is NUTS!!
I expect it to be all done in Extended. Why would anyone expect the contents of 
MyVariable to be butchered by storing the 33/1440 in single precision.

In other words
I expect the result of these both to be the same:

program TESTDBL1 ;

Var
AA : Extended;
BB : Extended;
CC : Extended;
DD : Extended;
EE : Extended;

begin
   AA := 8427;
   BB := 33;
   CC := 1440.0;
   DD := AA+BB/CC;
   EE := 8427+33/1440.0;
   WRITELN ( 'DD =' , DD : 20 : 20 ) ;
   WRITELN ( 'EE =' , EE : 20 : 20 ) ;
end.

But they are NOT
DD =8427.022916625000
EE =8427.022460937500

EE is WRONG and can never be considered right.   Why would ANY user with the 
code above expect that the 33/1440 would be done as a single, thus causing a 
loss of precision. 

Again:
"New behaviour: floating point constants are now considered to be of the lowest 
precision which doesn't cause data loss"

This was NOT done in the lowest precision which doesn't cause data loss.. we 
lost data   We are no longer Extended precision, anything at all we use EE 
for is WRONG.

This is CLEARLY WRONG!  The default should be the old way and if you don't like 
the Delphi warnings, you can make a switch to do it this new stupider and WRONG 
way.

I strongly feel this should be reverted, it's just wrong.   This makes no sense 
to me at all.   It's wrong to need to add a compiler directive to do things as 
they are expected by the vast majority to be, the directive should be needed 
for those few who even noticed the warnings in Delphi, and they were just 
warnings, not a substantial reduction in precision. 

James

>But not at the price of loss in precision ! Unless an explicit compiler switch 
>like --fast-math is passed 


___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Floating point question

2024-02-06 Thread Thomas Kurz via fpc-pascal
Thank you all

Finally I understand what's going wrong and can take care of that.

I'm now using the "{$MINFPCONSTPREC 64}" and have the correct result. Again, 
thank you for pointing me to that behavior!



- Original Message - 
From: Adriaan van Os via fpc-pascal 
To: FPC-Pascal users discussions 
Sent: Sunday, February 4, 2024, 13:50:48
Subject: [fpc-pascal] Floating point question

Jonas Maebe via fpc-pascal wrote:
> On 03/02/2024 18:42, James Richters via fpc-pascal wrote:
>> Constants are also evaluated wrong,you don’t know what that constant 
>> is going to be used for, so all steps of evaluating a constant MUST be 
>> done in extended by the compiler, or the answer is just wrong.

> See 
> https://wiki.freepascal.org/User_Changes_2.2.0#Floating_point_constants 
> and https://www.freepascal.org/daily/doc/prog/progsu19.html

I think this discussion shows that the 2.2 compiler change was a bad idea (for 
modes other than 
Delphi).

Regards,

Adriaan van Os
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Floating point question

2024-02-02 Thread Thomas Kurz via fpc-pascal
Well, 8427.0229, that's what I want.

But what I get is 8427.0224

And that's what I don't unterstand.



- Original Message - 
From: Bernd Oppolzer via fpc-pascal 
To: Bart via fpc-pascal 
Sent: Sunday, January 28, 2024, 10:13:07
Subject: [fpc-pascal] Floating point question

To simplify the problem further:

the addition of 12 /24.0 and the subtraction of 0.5 should be removed, IMO,
because both can be done with floats without loss of precision (0.5 can 
be represented exactly in float).

So the problem can be reproduced IMO with this small Pascal program:

program TESTDBL1 ;

var TT : REAL ;

begin (* HAUPTPROGRAMM *)
   TT := 8427 + 33 / 1440.0 ;
   WRITELN ( 'tt=' , TT : 20 : 20 ) ;
end (* HAUPTPROGRAMM *) .

With my compiler, REAL is always DOUBLE, and the computation is carried 
out by a P-Code interpreter
(or call it just-in-time compiler - much like Java), which is written in C.

The result is:

tt=8427.022916667879

and it is the same, no matter if I use this simplified computation or 
the original

tt := (8427 - 0.5) + (12 / 24.0) + (33 / 1440.0);

My value is between the two other values:

tt=8427.022916668000
tt=8427.022916667879
ee=8427.022916625000

The problem now is:

the printout of my value suggest an accuracy which in fact is not there, 
because with double, you can trust
only the first 16 decimal digits ... after that, all is speculative 
a.k.a. wrong. That's why FPC IMO rounds at this
place, prints the 8, and then only zeroes.

The extended format internally has more hex digits and therefore can 
reliably show more decimal digits.
But the last two are wrong, too (the exact value is 6... period).

HTH,
kind regards

Bernd



Am 27.01.2024 um 22:53 schrieb Bart via fpc-pascal:
> On Sat, Jan 27, 2024 at 6:23 PM Thomas Kurz via fpc-pascal
>   wrote:

>> Hmmm... I don't think I can understand that. If the precision of "double" 
>> were that bad, it wouldn't be possible to store dates up to a precision of 
>> milliseconds in a TDateTime. I have a discrepancy of 40 seconds here.
> Consider the following simplified program:
> 
> var
>tt: double;
>ee: extended;

> begin
>tt := (8427 - Double(0.5)) + (12/ Double(24.0)) +
> (33/Double(1440.0)) + (0/Double(86400.0));
>ee := (8427 - Extended(0.5)) + (12/ Extended(24.0)) +
> (33/Extended(1440.0)) + (0/Extended(86400.0));
>writeln('tt=',tt:20:20);
>writeln('ee=',ee:20:20);
> end.
> ===

> Now see what it outputs:

> C:\Users\Bart\LazarusProjecten\ConsoleProjecten>fpc test.pas
> Free Pascal Compiler version 3.2.2 [2021/05/15] for i386
> ...

> C:\Users\Bart\LazarusProjecten\ConsoleProjecten>test
> tt=8427.022916668000
> ee=8427.022916625000

> C:\Users\Bart\LazarusProjecten\ConsoleProjecten>fpc -Px86_64 test.pas
> Free Pascal Compiler version 3.2.2 [2021/05/15] for x86_64
> ..

> C:\Users\Bart\LazarusProjecten\ConsoleProjecten>test
> tt=8427.022916668000
> ee=8427.022916668000

> On Win64 both values are the same, because there Extended = Double.
> On Win32 the Extended version is a bit closer to the exact solution:
> 8427 - 1/2 + 1/2 + 33/1440 = 8427 + 11/480

> Simple as that.

> Bart
> ___
> fpc-pascal maillist  -fpc-pascal@lists.freepascal.org
> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Floating point question

2024-01-27 Thread Thomas Kurz via fpc-pascal
Hmmm... I don't think I can understand that. If the precision of "double" were 
that bad, it wouldn't be possible to store dates up to a precision of 
milliseconds in a TDateTime. I have a discrepancy of 40 seconds here.



- Original Message - 
From: Bart via fpc-pascal 
To: FPC-Pascal users discussions 
Sent: Saturday, January 27, 2024, 17:03:15
Subject: [fpc-pascal] Floating point question

On Sat, Jan 27, 2024 at 1:40 PM Thomas Kurz via fpc-pascal
 wrote:


> My problems are:

> 1. The "writeln" in line 32 correctly prints "0." when (cross-) compiling 
> to win64, but "39.375" when compiling to win32 (with ppc386).
On Win64 all math is done with double precision, on win32 all literal
floating point values in your code will be interpreted as Extended.
Cast everything to Double and the result will be the same on Win64 and Win32.


-- 
Bart
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] Floating point question

2024-01-27 Thread Thomas Kurz via fpc-pascal
Hello,

I'm facing some strange floating-point issues and cannot find what's actually 
wrong. OS is win64, but I'm even getting different results when targeting to 
win32.

Please consider the following program:

program test1;

{$mode objfpc}

function maketime (ayear, amonth, aday, ahour, aminute, asecond: integer): 
double;
  VAR
y: Int64 = 0;
m: Int64 = 0;
d: Int64 = 0;
f: Int64 = 0;
y2000: Int64 = 0;
ut: double;
tt: double;

  begin
y := ayear;
m := amonth;
d := aday;
f := (14 - m) DIV 12;

y2000 := (
(d - 365972956)
+ (1461 * (y + 100 - f)) DIV 4
+ (367 * (m - 2 + 12 * f)) DIV 12
- (3 * ((y + 1000100 - f) DIV 100)) DIV 4
);

assert (y2000 = 8427);

ut := (y2000 - 0.5) + (AHour / 24.0) + (AMinute / 1440.0) + (ASecond / 
86400.0);
tt := (8427 - 0.5) + (12/ 24.0) + (33/1440.0) + (0/86400.0);
writeln ((ut - tt) * 86400.0);
assert (ut = tt);
result := ut;
  end;

var t: double; diff: double;

begin
  t := maketime (2023, 1, 27, 12, 33, 0);
  t := (8427 - 0.5) + (12/ 24.0) + (33/1440.0) + (0/86400.0);
  diff := (t - 8427.02291670) * 86400.0;
  writeln (t);
  writeln (diff);
end.



My problems are:

1. The "writeln" in line 32 correctly prints "0." when (cross-) compiling 
to win64, but "39.375" when compiling to win32 (with ppc386).

2. According to both C, Sqlite and Excel, the value of "t" in line 41 should be 
"8427.0229167". FPC gives me a difference of approximately 39/86400.

Could someone point me to what I'm doing wrong, please. I have a feeling to 
miss the forest for the trees.

Thanks,
Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] Does the varargs specifier behave differently on 32 and 64 bit platforms?

2024-01-05 Thread Thomas Kurz via fpc-pascal
Hello,

I'm using a declaration like this

TYPE TRSMControl = FUNCTION (AData: PtrInt): PtrInt; CDECL; VARARGS;
VAR RSMControl: TRSMControl;

to make calls to a DLL function which expects a variable number of arguments. 
For example:

RSMControl (PtrInt(1), PtrInt(2), PtrInt(3))

On win32, this works fine. On win64, I get only the first argument correctly, 
the rest is garbage. Within the DLL, I subsequently access all parameters by 
taking the address of the first parameter and incrementing it in steps of 4 
bytes (or 8 bytes on win64).

I wonder whether I'm doing something wrong on the caller or callee side. The 
code worked reliably on win32, but I'm now trying to target win64 and am facing 
the problem that I cannot access the data that were passed. The CDECL calling 
convention should pass all arguments on the stack, and I expect subsequent 
arguments to be at subsequent memory addresses.

Does anyone have a clue for me?

Kind regards,
Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Daily snapshots?

2023-12-29 Thread Thomas Kurz via fpc-pascal
Thank you. That's what I've been looking for. Maybe the documentation at 
https://www.freepascal.org/docs-html/user/userse76.html could be updated 
regarding the new URL?

@Nico: Thanks for pointing me to Docker images, but I do not have Docker 
support on my Windows, unfortunately. I furthermore fear that it might be 
complicated to use a dockerized Lazarus.

Is there something special I have to consider when combining FPC-trunk with 
Lazarus 3.0? I'd like to replace the provided FPC 3.2.2 with the latest trunk 
snapshot. I guess I have to recompile all packages? Is there something else I 
need to do?

Thank you,
kind regards,
Thomas




- Original Message - 
From: Marco van de Voort via fpc-pascal 
To: fpc-pascal@lists.freepascal.org 
Sent: Friday, December 29, 2023, 12:37:54
Subject: [fpc-pascal] Daily snapshots?


Op 27/12/2023 om 12:38 schreef Thomas Kurz via fpc-pascal:

> as it seems to take longer for the next major release, I'd appreciate if 
> automated snapshots could be provided either daily or weekly.

> In the documentation, I found a link to 
> ftp://ftp.freepascal.org/pub/fpc/snapshot/trunk/ but I cannot login. I tried 
> with user=anynous and password=my-email-address.

> I don't mind the long time for the next release, but it'd help enormously to 
> have the option to download an up-to-date nightly build :)

The FTP site has been converted to http because many browsers deprecated 
the FTP protocol, try http://downloads.freepascal.org/fpc/snapshot/fixes/

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Procedures that work like WRITELN()

2023-12-27 Thread Thomas Kurz via fpc-pascal
I think he wants to define his own procedure.

The nearest thing that comes into my mind is using ARRAY OF CONST, but the call 
requires square brackets, then:

procedure myproc (x: string; y: array of const);
begin ... end;

myproc ('Hello world', ['Number 1', 'Number 2', 3, 4.0]);


- Original Message - 
From: Michael Van Canneyt via fpc-pascal 
To: ja...@productionautomation.net 
Sent: Wednesday, December 27, 2023, 12:40:24
Subject: [fpc-pascal] Procedures that work like WRITELN()



On Wed, 27 Dec 2023, James Richters via fpc-pascal wrote:

> I wanted to write what I thought should be a simple procedure, just instead
> of calling WRITELN() with some arguments,
> call WRITELOG() with the same arguments that you would use to write to a
> file, but my WRITELOG() procedure would
> write to the screen and the file.. but I can't figure out how to pass all
> the arguments to the two WRTIELNs.

> So..

> Procedure WriteLog(Filename:String, AllOtherAurguments:);
> Begin
>Writeln(Filename,AllOtherAurguments);
>Writeln(AllOtherAurguments);
> End;

> How can I make this work?  Since WRITELN can take any number of many kinds
> of arguments,
> how can I get them all and pass them along without knowing how many or what
> types they are?
> How does WRITELN even work when you don't know this information?

> I'm guessing there should be some way to do this, because WRITELN itself
> works, but how it could
> possibly work is not within my experience.

> The only way I could think of would be if there were versions of WRITELN
> with every combination
> of possible arguments, but that seems completely unmanageable and
> ridiculous,
> so there must be something more advanced going on, but maybe WRTELN is
> special and not something I can duplicate?

Writeln() is special. You cannot duplicate it.

What you can do is use WriteStr(), it has the same action as Writeln() but
writes to a string instead of a file.

https://www.freepascal.org/docs-html/current/rtl/system/writestr.html

Michael.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] Daily snapshots?

2023-12-27 Thread Thomas Kurz via fpc-pascal
Hello,

as it seems to take longer for the next major release, I'd appreciate if 
automated snapshots could be provided either daily or weekly.

In the documentation, I found a link to 
ftp://ftp.freepascal.org/pub/fpc/snapshot/trunk/ but I cannot login. I tried 
with user=anynous and password=my-email-address.

I don't mind the long time for the next release, but it'd help enormously to 
have the option to download an up-to-date nightly build :)

Kind regards,
Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Error: compilation raised exception internally

2023-10-21 Thread Thomas Kurz via fpc-pascal
> An exception or an internal error during compilation should *always* be
> reported.
> Please also provide a minimal, self contained example that shows the
> problem.

This is not always trivial because the internal errors are sometimes quite 
fiddly. I have a project in which an internal error occurs sometimes. When I do 
a "cleanup and build" (in Lazarus), it works well. There seems to be an 
influence of the order in which units are compiled, because I can change code 
in many places without getting the internal error again. But when I change code 
in other units, I get the internal error, but it's clearly uncorrelated to the 
line at which it occurs.

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] What is webasssembly?

2023-10-12 Thread Thomas Kurz via fpc-pascal
> Does this mean I can code an application in Pascal and use webassembly
to turn it into a web application? If so, could you please point me to
some simple examples?

Without having WebAssembly used yet: As far as I understand, that should be 
possible.

The "entry point" is here: https://wiki.freepascal.org/WebAssembly

But I'd appreciate some more (and simple) examples, too. +1 for that :)

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] msdos: unresolved external

2023-07-12 Thread Thomas Kurz via fpc-pascal
I have to extend code from QuickBasic and am using the "msdos" target from FPC 
3.2 for that purpose. The resulting exe file is linked with Microsoft Linker 
for DOS version 5.10. It links *.a files created both from QuickBasic and FPC. 
The memory model is i8086-small.

Basically, it works well.

I have to use file functions now (Assign, Reset, Close) and as soon as I start 
using any of these, linking fails with the following unresolved dependencies:

Z:\SYSTEM.LIB(prt0s.asm) : error L2029: '__stklen' : unresolved external
Z:\SYSTEM.LIB(prt0s.asm) : error L2029: 'PASCALMAIN' : unresolved external
Z:\SYSTEM.LIB(prt0s.asm) : error L2029: '___heap' : unresolved external
Z:\SYSTEM.LIB(system0s896.o) : error L2029: 'INITFINAL' : unresolved external
Z:\SYSTEM.LIB(prt0s.asm) : error L2029: '___stacktop' : unresolved external
Z:\SYSTEM.LIB(prt0s.asm) : error L2029: '__fpc_stackplusmaxheap_in_para' : 
unresolved external

To me, it looks as if these were very basic code for memory management. I found 
(e.g.) "__fpc_stackplusmaxheap_in_para" in prt0comn.asm in which is declared 
"extern". But I'm unable to see which external object is responsible for it.

Note that I'm *not* compiling and linking the full program with FPC, I'm only 
developing parts of it. The main part comes from QuickBasic. But as FPC is able 
to build fully working MS-DOS executables in which (I assume) it needs the 
criticized external dependencies as well, they should exist somewhere, 
shouldn't they? But what do I need to link against for them to be included?

Thanks for helping,
Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Parse JSON

2023-06-25 Thread Thomas Kurz via fpc-pascal
fpJson fully supports JSON:

https://www.freepascal.org/docs-html/fcl/fpjson/index.html
https://wiki.lazarus.freepascal.org/JSON

There's also JSON support in the LGenerics package, but it's not a bundled 
package as far as I know.

Thomas


- Original Message - 
From: Darius Blaszyk via fpc-pascal 
To: FPC-Pascal users discussions 
Sent: Friday, June 23, 2023, 16:02:26
Subject: [fpc-pascal] Parse JSON

Hi all,

I've hardly done anything with JSON in Freepascal before, so apologies 
for the trivial question. I want to traverse an array in JSON and 
retrieve the elements (which I don't know what they are in advance) one 
by one. An example of the JSON file is given below.

"keywords": {
   "key": "value",
   "key1": "value1",
   "key2": "value2"
},

Ideally, I'd like to be able to stick to the FPC out-of-the-box library. 
Any help would be appreciated.

Rgds, Darius

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] LoadLibrary, FreeLibrary & Threads (win32)

2023-06-22 Thread Thomas Kurz via fpc-pascal
Dear all,

I have spent 2 days now tracking an access violation in my app which I couldn't 
debug well because it occured somewhere where no debug info was available, but 
obviously during a call to FreeLibrary.

I don't know whether I am allowed to do this or not, but as far as I have read 
from the Microsoft docs about using libraries [1,2] I didn't find a note that 
my approach is forbidden. (Of course, I may have overread it.)

[1] 
https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices
[2] 
https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya

What I did is to call LoadLibrary in a different thread than the main thread. 
The corresponding call to FreeLibrary on the other hand was done in the main 
thread.

Question 1: Is this legal on Windows? If not, we're finished here and you can 
skip the rest ;)

However, if it *is* legal, I'd need some help with FPC. Here's a minimal 
example:

***

library dummylib;

uses
  Classes;

begin
end.

***

program project1;

uses SysUtils, Types, Classes;

type TLoadLibThread = class(TThread)
  procedure Execute; override;
  var FHandle: THandle;
end;

procedure TLoadLibThread.Execute;
begin
  FHandle := LoadLibrary('dummylib.dll');
end;

var h: THandle = NilHandle;

begin
  with TLoadLibThread.Create(FALSE) do begin
WaitFor;
h := FHandle;
Free;
  end;
  Assert (h <> NilHandle);
  FreeLibrary (h); 
end.

***

The call to FreeLibrary causes an "access violation writing to address $14".

I also tried to follow the advice in the "multithreaded application tutorial" 
in the wiki ("initialize the FPC's threading system by creating a dummy 
thread"), but this doesn't make any difference.

I assume that I have some obviouy error and am just too blind to see, so I'd 
appreciate someone pointing me to it.

Thanks,
Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Legitimate use of for and break

2023-06-16 Thread Thomas Kurz via fpc-pascal
I'm certainly not the expert in FPC's details, so maybe there'll you'll get a 
better answer. I just tell you my point of view.

>> It's an array with a terminator
>>string? Probably the length of the array should be set instead of
>>doing string compares every loop.
>
> I need to set it in the var declaration, right?

I don't quite understand this question, but of it's about the length of the 
array, there are two ways:

a) Statically as "VAR x: array[1..6] of string"
b) Dynamically:

var x: array of string;  // I prefer x: TStringArray instead, but this requires 
the classes unit IIRC
begin
  SetLength(x, 6); // will always declare a zero-based index, i.e. x[0]..x[5]
  // the advantage is you can change this lateron:
  SetLength(x, 7); // keeps items 0..5 and adds x[6]
end;


>   words[ss] := '~';
>  Is it legitimate to set elements inside a for loop?

Yes, of course. You're not allow to change the loop variable, but you can 
assign array values there without any problem. In fact, with larger arrays, it 
may even be the *only* way to do it. (Except using a different loop type like 
while or repeat, of course.)

Imagine you want to have x^2 for x = 0...1000:

var y: array[0..1000] of integer; x: integer;
begin
  for x:=0 to 1000 do  // ; I prefer: for x := Low(y) to High(y) do
  y[x] := x * x;
end;

If you couldn't do that, you'd have to write

y[0] := 0;
y[1] := 1;
y[2] := 4;
y[3] := 9;


>   if words[ss] = '~' then
>  break
>   ^  IS IT legitimate to use a break (or continue) inside
> a for loop?

As far as I know, there are different opinions about this. The clear answer to 
whether it's *legitimate* is YES, because that's what "break" is meant for.


Whether it's elegant is a different question. In my opinion YES because it 
often gives better readable code than nested "if" statements inside the loop. 
But I've also read that using "break" is discouraged because it shows a bad 
choice of the loop range.

Kind regards,
Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Freeing memory with exceptions

2023-05-26 Thread Thomas Kurz via fpc-pascal
I do not think that this discussion is of any value. If you need to care for 
every byte, you'd better consider using asm. In times of e-mail clients using 
far more than 100 MB of disk and RAM memory or simple Android apps having 
several dozens of megabytes because of the included trackers, it seems 
ridiculous to discuss about 39 bytes!


- Original Message - 
From: Benito van der Zander via fpc-pascal 
To: fpc-pascal@lists.freepascal.org 
Sent: Thursday, May 25, 2023, 22:49:08
Subject: [fpc-pascal] Freeing memory with exceptions

Hi,


> That 99.99% of people does use it, indicates they simply take the 
> overhead because
> of the advantages that the managed types offer. 

Or they simply do not know about the overhead

Like I was writing all my code on Windows 98, and never noticed any 
overhead, until I started running benchmarks on  Linux.

Bye,
Benito
On 25.05.23 07:58, Michael Van Canneyt via fpc-pascal wrote:


> On Thu, 25 May 2023, Hairy Pixels via fpc-pascal wrote:



>>> On May 24, 2023, at 10:11 PM, Sven Barth via fpc-pascal 
>>>  wrote:

>>> You must have $H+ on and those are AnsiStrings? Why is there 
>>> exception handling involved with AnsiString? I guess it needs this 
>>> just in case an exception is thrown somewhere in the call stack?

>>> Because Ansi- and UnicodeString are managed types. *All* managed 
>>> types managed string types, interfaces, Variants, managed records) 
>>> must be finalized correctly even if an exception occurs.


>> That's a problem with exceptions then, they are baked into the language
>> and impose a cost on all managed types now even if we use them or 
>> not. Even disabling the implicit stack frames (forgot what it's 
>> called) doesn't
>> get around this right?

> Why do you insist it is a problem ?

> Simply don't use managed types and don't use exceptions if you don't 
> like the
> overhead they cause. It's still perfectly possible: avoid the sysutils 
> unit
> and you're all set. The system unit does not use exceptions.

> That 99.99% of people does use it, indicates they simply take the 
> overhead because
> of the advantages that the managed types offer.

> Which is not to say that FPC should not strive to minimize the overhead.
> Conceivably there is some gain possible on non-windows platforms.

> Michael.
> ___
> fpc-pascal maillist  - fpc-pascal@lists.freepascal.org
> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Multiple enumerators per class

2023-05-12 Thread Thomas Kurz via fpc-pascal
It's part of generics.collections and located in 
fpc\3.2.2\source\packages\rtl-generics\src\*

- Original Message - 
From: Hairy Pixels via fpc-pascal 
To: FPC-Pascal users discussions 
Sent: Friday, May 12, 2023, 14:59:11
Subject: [fpc-pascal] Multiple enumerators per class



> On May 12, 2023, at 7:24 PM, Marco van de Voort via fpc-pascal 
>  wrote:

> Op 12/05/2023 om 14:16 schreef Hairy Pixels via fpc-pascal:
>> Is it possible to have multiple enumerators on one class?

> Yes, see e.g. TDictionary that allows iterations over keys and values and 
> both. There is only one default iterator, but you can have some property that 
> has its own iterator.

Where is TDictionary located so I can see the class definition? can't seem to 
find it

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Record Constructors which differ in parameter lists

2023-05-12 Thread Thomas Kurz via fpc-pascal
> I would expect the type helper to remain functional. The types are the same
> for all purposes except they have a different RTTI entry.

But this behaviour seems inconsistent to me. For example:

With "var x:double" I can use "x.IsNan". With TDateTime, which is defined as 
"type TDateTime = type Double", I cannot.

With strings, I can use "x.IsEmpty". With Utf8String, which is defined as "type 
TUtf8String = type AnsiString", I cannot.

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Record Constructors which differ in parameter lists

2023-05-10 Thread Thomas Kurz via fpc-pascal
Dear Michael,

thank you for the explanation. I understand that the helper overwrites the 
original constructor. But...

I have defined "type TSomething = type TVec3f" (note the second "type"). So 
from my perspective, I'd assume that the TSomethingHelper doesn't apply to 
TVec3f at all because TSomething is defined as a new type, not only an alias 
for TVec3f.


- Original Message - 
From: Michael Van Canneyt via fpc-pascal 
To: Thomas Kurz via fpc-pascal 
Sent: Tuesday, May 9, 2023, 23:55:47
Subject: [fpc-pascal] Record Constructors which differ in parameter lists



On Tue, 9 May 2023, Thomas Kurz via fpc-pascal wrote:

> Hello,

> let's take the following example:

> program Project1;

> {$MODE OBJFPC}
> {$MODESWITCH ADVANCEDRECORDS}
> {$MODESWITCH TYPEHELPERS}

> type TVec3f = record
>  x, y, z: Double;
>  constructor Create (a1, a2, a3: Double);
> end;

> type TSomething = type TVec3f;

> type TSomethingHelper = type helper for TSomething
>  constructor Create (a1, a2: Double);
> end;

> constructor TVec3f.Create (a1, a2, a3: Double);
> begin
>  Self.x := a1;
>  Self.y := a2;
>  Self.z := a3;
> end;

> constructor TSomethingHelper.Create (a1, a2: Double);
> begin
>  Self.x := a1;
>  Self.y := a2;
>  Self.z := 1 - a1 - a2;
> end;

> var f: TVec3f;

> begin
>  f := TVec3f.Create (0.0, 0.0, 0.0); // <-- error here
> end.


> I get the error:
> project1.lpr(35,37) Error: Wrong number of parameters specified for call to 
> "Create"
> project1.lpr(25,30) Error: Found declaration: constructor 
> Create(Double;Double);

> So, obviously, FPC tries to apply the helper of TSomething (which should be 
> decoupled from TVec3f because of the "type TVec3f" declaration) to TVec3f 
> which hasn't defined any constructor with 2 parameters.

> Is this intended behavior or should I report it as a bug?

This is intended behaviour since declarations in helpers always take
precedence over the methods in the class/record.

Try to add overload; to the constructor in the helper. This is a hint to the
compiler that it should look for other methods.

Michael.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] Record Constructors which differ in parameter lists

2023-05-09 Thread Thomas Kurz via fpc-pascal
Hello,

let's take the following example:

program Project1;

{$MODE OBJFPC}
{$MODESWITCH ADVANCEDRECORDS}
{$MODESWITCH TYPEHELPERS}

type TVec3f = record
  x, y, z: Double;
  constructor Create (a1, a2, a3: Double);
end;

type TSomething = type TVec3f;

type TSomethingHelper = type helper for TSomething
  constructor Create (a1, a2: Double);
end;

constructor TVec3f.Create (a1, a2, a3: Double);
begin
  Self.x := a1;
  Self.y := a2;
  Self.z := a3;
end;

constructor TSomethingHelper.Create (a1, a2: Double);
begin
  Self.x := a1;
  Self.y := a2;
  Self.z := 1 - a1 - a2;
end;

var f: TVec3f;

begin
  f := TVec3f.Create (0.0, 0.0, 0.0); // <-- error here
end.


I get the error:
project1.lpr(35,37) Error: Wrong number of parameters specified for call to 
"Create"
project1.lpr(25,30) Error: Found declaration: constructor Create(Double;Double);

So, obviously, FPC tries to apply the helper of TSomething (which should be 
decoupled from TVec3f because of the "type TVec3f" declaration) to TVec3f which 
hasn't defined any constructor with 2 parameters.

Is this intended behavior or should I report it as a bug?

Versions used:
Lazarus 2.3.0 (rev main-2_3-3525-g9208f17734) FPC 3.3.1 i386-win32-win32/win64
(FPC is not the most recent build, it's about 2~3 weeks old)

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] StrIComp

2023-04-29 Thread Thomas Kurz via fpc-pascal
Just a very minor question:

Is it intentional that StrIComp (from the strings unit) gives an access 
violation if one of its arguments is NIL?

I hardly work with PChars so this is a serious question from me.

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] How to use StrToDateTime() to convert a string with no delimiters?

2023-04-24 Thread Thomas Kurz via fpc-pascal
I always use ScanDateTime for such purposes:

https://www.freepascal.org/docs-html/rtl/dateutils/scandatetime.html

You can explicitly define the pattern.



- Original Message - 
From: Bo Berglund via fpc-pascal 
To: fpc-pascal@lists.freepascal.org 
Sent: Monday, April 24, 2023, 20:08:01
Subject: [fpc-pascal] How to use StrToDateTime() to convert a string with no 
delimiters?

I have a device that sends data over the serial port with a timestamp in this
format:

(230424194642W)

This is coded as yymmddhhnnss and the last char designates daylight savings
(S)ummer or normal (W)inter time. In the example above it is W for normal winter
time.

What I have done so far is:
- Remove the () at start and end
- Remove the W at the end
- Add 20 (as the century) up front
- Insert a space after the 6th char (so between date and time
- Set the TFormatsettings like this (to say that there are no separators):
  FS.DateSeparator := #0; (Is this how it is done?)
  FS.TimeSeparator := #0;
- Then the call:
  Value := StrToDateTime(sValue, FS); (Value is declared as TDateTime)

This triggers an exception with the message:
 "194522" is not a valid time

What is the proper way to decode a string as shown above?
Since the date part could be decoded, why not also the time part, after all I
separated the two with a space and set the same separators?


-- 
Bo Berglund
Developer in Sweden

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] DateUtils: (Try)ModifiedJulianDateToDateTime not implemented

2023-04-16 Thread Thomas Kurz via fpc-pascal
Hello,

I have seen that the functions for dealing with modified Julian dates are 
documented as "not yet implemented". Is there a particular reason for that? If 
not, I'd make an implementation and post it on Gitlab.

Kind regards,
Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Converting old pascal written for Pascal/MT+ compiler

2023-04-04 Thread Thomas Kurz via fpc-pascal
Didn't know that either:

"It should be stressed that typed constants are automatically initialized at 
program start. This is also true for local typed constants and initialized 
variables. Local typed constants are also initialized at program start. If 
their value was changed during previous invocations of the function, they will 
retain their changed value, i. e. they are not initialized each time the 
function is invoked."

described here: 
https://www.freepascal.org/docs-html/current/ref/refse10.html#x22-210002.2


- Original Message - 
From: Travis Siegel via fpc-pascal 
To: FPC-Pascal users discussions 
Sent: Tuesday, April 4, 2023, 20:34:10
Subject: [fpc-pascal] Converting old pascal written for Pascal/MT+ compiler

I'm not positive, because I've never used them, but I'm pretty sure 
variables configured as const, can't be changed once they're defined.  
If that's your intent, then feel free to use them, but it sounds like 
you're trying to make variables (not constant values) last for the whole 
program, with manipulation being allowed.  In that, case, simply define 
them in the var section before you do any of the functions and 
procedures.  That will make them visible for the whole program, and they 
won't go out of scope.  I know many folks contend that global variables 
should be kept to a minimum, and scope should be carefully evaluated, 
and only allow variables to be usable when they're actually needed, and 
to some degree, I agree, but there's times when it's just too darned 
convenient to have something accessible for the whole program over 
multiple functions/procedures, and in those cases, I see nothing wrong 
with having as many globals as you need.

Often, when I'm doing a quick and dirty program, (I.E. one to change a 
data file from one format to another), I won't even bother with 
functions and procedures, just write the whole program as one big main 
procedure, since it's only being run once or twice, then never used 
again, I see nothing wrong with this approach either, and in that case, 
all variables are global.

No reason you can't do the same, and not depend on quirks of the 
compiler to keep your items in scope especially when they clearly 
shouldn't be.



Am 04.04.2023 um 08:16 schrieb Jacob Kroon via fpc-pascal:

>> I was able to write a couple of perl-scripts that are able to convert 
>> my old Pascal sources to something that fpc can parse. Amongst other 
>> things, the scripts inject the "public name"/"external name" 
>> annotations so that the program can link.

>> But I suspect I have a new problem: With the old Pascal/MT+ compiler 
>> it would appear that local variables declared in functions/procedures 
>> have a life-time that spans the whole program, like a "static" 
>> declared variable in C. With fpc, it looks like locally declared 
>> variables are automatic, put on the stack(?), and so they go out of 
>> existence once out of scope ?

>> The program depends on this feature in the old compiler. I did some 
>> googling and found that putting local variables in a "const" section 
>> instead of "var" would make them have a "whole-program" lifetime, but 
>> then I need to provide them with an initial value.

>> Do I have any other option besides changing from "var" to "const" 
>> everywhere, and provide initial values in all declarations ?

>> Regards
>> Jacob

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Converting Delphi7 code to FreePascal with interfacing to protection key?

2023-03-21 Thread Thomas Kurz via fpc-pascal
There will surely be better responses than mine, but imho there is an 
inconsistency in your code: Near/Far calls are a relict of the 16-bit 
DOS/Win3.x era. The {$F+} switch should be completely obsolete for both Win32 
and Win64 executables.

.obj files are compiled code (pieces) which are not yet linked together. I 
cannot imagine that there is a chance to convert a 32-bit .obj file into a 
.64-bit .obj file without recompilation (i.e. having the sources). So I'd 
assume that you are stuck to the 32-bit architecture or you might try to obtain 
a 64-bit .obj from the manufacturer. Maybe he's even released a complete 
library with a documented API in the meantime? (Even though the hardware key is 
old it could still be supported as part of the driver series of the 
manufacturer's current hardware.)



- Original Message - 
From: Bo Berglund via fpc-pascal 
To: fpc-pascal@lists.freepascal.org 
Sent: Tuesday, March 21, 2023, 23:49:30
Subject: [fpc-pascal] Converting Delphi7 code to FreePascal with interfacing to 
protection key?

We have a number of old Delphi7 applications which are in need of porting over
to FreePascal. I have successfully done a number of these ports in the last few
years...
But now I am up against a bit of a problem regarding software we have protected
using an USB connected hardware key originally bought from Rainbow, a company
that has been bought up in several steps and is now named THALES.

Anyway, our software interfaces to the SuperPro protection keys is via a Windows
driver from THALES and they have provided a software integration kit way back
when we started using the keys.
It consist of a Delphi unit basically containing a list of definitions of
available API functions into the driver looking like this:

--
{ Force FAR calls }
{$F+}

INTERFACE

CONST
 { SuperPro API error codes }
 SP_SUCCESS = 0;
 
 SPRO_MAX_QUERY_SIZE= 56;

TYPE

RB_SPRO_APIPACKET  = ARRAY [1..1028] OF CHAR;  { Spro API Packet }
RB_SPRO_APIPACKET_PTR  = ^RB_SPRO_APIPACKET;

FUNCTION SproInitialize( ApiPacket : RB_SPRO_APIPACKET_PTR   ) : WORD;
FUNCTION SproGetExtendedStatus( ApiPacket : RB_SPRO_APIPACKET_PTR ) : WORD;


IMPLEMENTATION
USES
   Windows;

{$L SPROMEPS.OBJ}  { LINK WITH THE SUPERPRO OBJECT FILE }
{ External functions }

FUNCTION RNBOsproFormatPacket( ApiPacket : RB_SPRO_APIPACKET_PTR;
   thePacketSize : WORD ) : WORD; STDCALL; EXTERNAL;

FUNCTION RNBOsproInitialize( ApiPacket : RB_SPRO_APIPACKET_PTR ) : WORD;
STDCALL; EXTERNAL;


FUNCTION SproInitialize( ApiPacket : RB_SPRO_APIPACKET_PTR ) : WORD;
VAR
returnVal : WORD;
BEGIN
returnVal := RNBOsproFormatPacket (ApiPacket, RB_SPRO_APIPACKET_SIZE);
IF returnVal <> SP_SUCCESS THEN
   SproInitialize := returnVal
ELSE
   SproInitialize := RNBOsproInitialize (ApiPacket);
END; { SproInitialize }




BEGIN
END.
--

Obviously being from the time when it was received the OBJ file SPROMEPS.OBJ to
be linked in is a 32 bit type, so the ported programs need to be compiled/linked
into a 32 bit exe file on Windows.

Questions:
--

1) How should I go about translating the above to current FreePascal syntax?

This involves:
{ Force FAR calls }
{$F+}

{$L SPROMEPS.OBJ}  { LINK WITH THE SUPERPRO OBJECT FILE }

2) Is there a way to translate/convert the 32 bit Windows SPROMEPS.OBJ file into
a 64 bit one such that it could be used for a 64 bit fpc compiler?
It is the interface to the protection key driver on the Windows system...

It does work for our 32 bit Delphi7 programs on Windows 10 x64, so there must be
some 32<->64 bit handling in Windows maybe?


-- 
Bo Berglund
Developer in Sweden

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] Working with anonymous functions

2023-03-10 Thread Thomas Kurz via fpc-pascal
Dear all,

I'm testing FPC-trunk and I'm especially interested in using anonymous 
functions because they should simplify working with TThread.Synchronize and 
others a lot.

I stumbled upon an issue which I'd like to post here first because I am not 
sure whether it's a bug or just a wrong usage on my side.

Here's a small example:


program project1;

{$modeswitch anonymousfunctions}
{$modeswitch functionreferences}

uses Classes, EventLog, SysUtils;

type
  TTest = class
FOnLog: TLogMessageEvent;
procedure CallOnLog (AEventType: TEventType; AMessage: String);
  end;

procedure TTest.CallOnLog (AEventType: TEventType; AMessage: String);

var
  r: reference to TThreadMethod = nil;
  m: TThreadMethod = nil;

begin
  // This doesn't work because the anonymous procedure is
  // capturing local symbols. I understand that this doesn't work.
  m := procedure
begin
  FOnLog (Self, AEventType, AMessage);
end;

  // As far as I have understood
  // https://forum.lazarus.freepascal.org/index.php/topic,59468.0.html
  // the solution should be to use a "reference to".
  // In fact, assignment works as expected:
  r := procedure
begin
  FOnLog (Self, AEventType, AMessage);
end;

  // But I seem not to have any change to pass the reference.
  // Both versions fail:
  TThread.ForceQueue (NIL, r());
  TThread.ForceQueue (NIL, @r);
end;

begin
end.


As you can see, the goal is to call TThread.ForceQueue. Of course, the easiest 
solution was having an overloaded "TThread.ForceQueue (TThread, 
TThreadProcedure)" as is the case with Delphi. I have already posted a feature 
request on Github.

But I don't know why I can't use a "reference to TThreadMethod". If I 
understand the feature announcement correctly, this should work, shouldn't it?

Kind regards,
Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Strange floating-point result

2022-11-11 Thread Thomas Kurz via fpc-pascal
Understood, ok. Thanks for your explanation.

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] Strange floating-point result

2022-11-11 Thread Thomas Kurz via fpc-pascal
Hello,

by chance, I stumbled upon a strange behavior in floating-point calculation. 
Here's the example:

program Project1;

var
  f: double;
  n: integer = 1758;
  m: integer = 0;

begin
  f := n * 1.2E6 + (2*m+1) * 50E3; // 2109650048
  f := Double(n) * 1.2E6 + Double(2*m+1) * 50E3; // 210965
end.

Why do I have to explicitly cast Integer to Double here? I never did that 
before and am a bit worried whether I could get wrong results elsewhere, too, 
without having them noticed yet. And how does the first value come about?

FPC is 3.2.2 on Win64, targeting Win64.

Kind regards,
Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] How to assign overloaded event handler?

2022-09-14 Thread Thomas Kurz via fpc-pascal
I don't know whether this is actually a bug or not but I cannot find a hint in 
the documentation.

It seems that methods assigned to an event handler are not allowed to be 
overloaded. Or, to be more precise, FPC always uses the first declaration 
regardless whether it fits or not.

Example:


program Project1;

uses Classes;

type TTest = class(TObject)
  procedure SomeEvent (Sender: NativeInt); overload;
  procedure SomeEvent (Sender: TObject); overload;
end;

procedure TTest.SomeEvent (Sender: TObject);
begin
end;

procedure TTest.SomeEvent (Sender: NativeInt);
begin
end;

var
  x: TTest;
  y: TStringList;

begin
  x := TTest.Create;
  y := TStringList.Create;
  y.OnChange := @x.SomeEvent;
end.



This doesn't work:

project1.lpr(25,17) Error: Incompatible types: got "" expected ""

However, when switching both SomeEvent declarations so that the "TObject" 
variant appears first, it does work.

Imho, it should considered a bug because the compiler should be able to detect 
that there is a matching overloaded method and assign that one.

In my simple example, the solution is, of course, to swap declarations. But I'm 
assigning event handler to a generic class and need event handlers with 
different types. And it would be helpful if they had the same name when serving 
the same purpose.

Is there a possibility to tell FPC to use a particular method in the 
assignment? Something like "OnChange:=@(TNotifyEvent(SomeEvent))"?

Kind regards,
Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Get highest element of a StringList

2022-09-10 Thread Thomas Kurz via fpc-pascal
If you just don't like the "-1" for readability, you might also wan't to 
consider using

for i := 0 to Pred(f.Count) do ...


- Original Message ----- 
From: Thomas Kurz via fpc-pascal 
To: 'FPC-Pascal users discussions' 
Sent: Saturday, September 10, 2022, 21:37:34
Subject: [fpc-pascal] Get highest element of a StringList

Try this (note the "modeswitch"):

program Project1;

{$modeswitch typehelpers}

uses
  Classes,
  SysUtils;

type TStringListHelper = class helper for TStringList
  function High: NativeInt;
end;

function TStringListHelper.High: NativeInt;
begin
  Exit (Self.Count-1);
end;

var
  f: TStringList = nil;
  i: Integer;

begin
  f := TStringList.Create;
  f.Add ('hallo');
  f.Add ('welt');
  f.Add ('!');
  for i := 0 to f.High do Writeln (f[i]);
  FreeAndNil (f);
end.





- Original Message - 
From: James Richters via fpc-pascal 
To: 'FPC-Pascal users discussions' 
Sent: Saturday, September 10, 2022, 19:57:51
Subject: [fpc-pascal] Get highest element of a StringList

This Helper sounds like a nice way to do it.  I need the numerical index of
the loop so this would be more straight forward.
Would I then do something like :
For I:= 0 to MyStringList.High Do 
?

When I try to add the Type statement:
type TStringListHelper = class helper for TStringList function High:
NativeInt; end;
I getError: Identifier not found "class"

I have the Classes unit.  Is there something else I am missing?

James

>Another alternative would be declaring a helper:

>type TStringListHelper = class helper for TStringList function High:
NativeInt; end;

>function TStringListHelper.High: NativeInt; begin
>  Exit (Self.Count-1);
>end;

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Get highest element of a StringList

2022-09-10 Thread Thomas Kurz via fpc-pascal
Try this (note the "modeswitch"):

program Project1;

{$modeswitch typehelpers}

uses
  Classes,
  SysUtils;

type TStringListHelper = class helper for TStringList
  function High: NativeInt;
end;

function TStringListHelper.High: NativeInt;
begin
  Exit (Self.Count-1);
end;

var
  f: TStringList = nil;
  i: Integer;

begin
  f := TStringList.Create;
  f.Add ('hallo');
  f.Add ('welt');
  f.Add ('!');
  for i := 0 to f.High do Writeln (f[i]);
  FreeAndNil (f);
end.





- Original Message - 
From: James Richters via fpc-pascal 
To: 'FPC-Pascal users discussions' 
Sent: Saturday, September 10, 2022, 19:57:51
Subject: [fpc-pascal] Get highest element of a StringList

This Helper sounds like a nice way to do it.  I need the numerical index of
the loop so this would be more straight forward.
Would I then do something like :
For I:= 0 to MyStringList.High Do 
?

When I try to add the Type statement:
type TStringListHelper = class helper for TStringList function High:
NativeInt; end;
I getError: Identifier not found "class"

I have the Classes unit.  Is there something else I am missing?

James

>Another alternative would be declaring a helper:

>type TStringListHelper = class helper for TStringList function High:
NativeInt; end;

>function TStringListHelper.High: NativeInt; begin
>  Exit (Self.Count-1);
>end;

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Get highest element of a StringList

2022-09-10 Thread Thomas Kurz via fpc-pascal
Another alternative would be declaring a helper:

type TStringListHelper = class helper for TStringList
function High: NativeInt;
end;

function TStringListHelper.High: NativeInt;
begin
  Exit (Self.Count-1);
end;


- Original Message - 
From: James Richters via fpc-pascal 
To: 'FPC-Pascal users discussions' 
Sent: Saturday, September 10, 2022, 18:01:20
Subject: [fpc-pascal] Get highest element of a StringList

I thought I would try:

For Loop := 0 to High(MyStringList) do

But I get "Error: Type mismatch"

Is there a way to get the highest element of a stringlist other than:

For Loop := 0 to MyStringList.Count-1 do

It would be nice to not have the -1
Could High() be made to work if the argument was a stringlist?

James

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Teaching Kids Using Free Pascal

2022-08-27 Thread Thomas Kurz via fpc-pascal
I currently have only a few missing symbols, mostly math related:

Hint: (11030) Start of reading config file 
P:\Lazarus\fpc\3.2.2\bin\x86_64-win64\fpc.cfg
Hint: (11031) End of reading config file 
P:\Lazarus\fpc\3.2.2\bin\x86_64-win64\fpc.cfg
Warning: (11018) You are using the obsolete switch -St
Hint: (11030) Start of reading config file X:\Settings\Lazarus\fpcext.cfg
Hint: (11031) End of reading config file X:\Settings\Lazarus\fpcext.cfg
Free Pascal Compiler version 3.2.2 [2022/01/02] for x86_64
Copyright (c) 1993-2021 by Florian Klaempfl and others
(1002) Target OS: Win64 for x64
(3104) Compiling project1.lpr
(9015) Linking Z:\project1.exe
Z:\project1.lpr(11,1) Error: Undefined symbol: sin
Z:\project1.lpr(11,1) Error: Undefined symbol: cos
Z:\project1.lpr(11,1) Error: Undefined symbol: __imp___acrt_iob_func
Z:\project1.lpr(11,1) Error: Undefined symbol: sqrt
Z:\project1.lpr(11,1) Error: Undefined symbol: pow
Z:\project1.lpr(11,1) Error: Undefined symbol: floor
Z:\project1.lpr(11,1) Fatal: (10026) There were 6 errors compiling module, 
stopping
Fatal: (1018) Compilation aborted
Error: P:\Lazarus\fpc\3.2.2\bin\x86_64-win64\ppcx64.exe returned an error 
exitcode

The most tricky one seens to be "__imp___acrt_iob_func". A google search 
indicated that this one apparently is "hard-coded into the Go linker".

So my questions are:

- Has libchipmunk-win.a been compiled with Go? (I know that in your original 
message, you wrote about C, but I just want to be sure.)
- Have you tried using the Go linker instead of FPCs one?

But I will stay with it.





- Original Message - 
From: Michael Van Canneyt via fpc-pascal 
To: Anthony Walter via fpc-pascal 
Sent: Saturday, August 27, 2022, 11:14:55
Subject: [fpc-pascal] Teaching Kids Using Free Pascal



On Sat, 27 Aug 2022, Anthony Walter via fpc-pascal wrote:

> Some of you might not be aware, but I teach small groups of kids ages 8-16
> computer programming and digital electronics. When teaching programming I
> often use Free Pascal and Lazarus, and try to come up with exciting ideas.

> Over the past few weeks, I've taught my high school kids who have completed
> Algebra I programming using Linear Algebra. To help illustrate vectors,
> and matrices, I wrote a small program using Free Pascal to help them
> understand the sin(a) function.

> I thought I'd share the result:

> https://streamable.com/b5ojtt

A nice result, thank you for sharing this.

I talked to the chairman of the Free Pascal & Lazarus foundation and showed
your mail.

The subject of teaching kids how to program in Pascal and in particular using 
it for math
problems is something that is close to his heart (and to mine, as this is
exactly how I rolled into Free Pascal a quarter of a century ago).

He is also the editor of the Blaise Pascal magazine, and has published a
book by a dutch author that combines exactly these subjects:

https://www.blaisepascalmagazine.eu/product/books-computer-graphics-math-games-download-pdf/

I explained him your problem, and he agreed that the foundation should
assist in trying to solve this problem.

Therefore, for all:

If someone presents a solution that can be distributed with the compiler &
FPC which solves or considerably eases the problem (for instance a glue unit
that can be included to provide most of the missing symbols, some compiler
routines that aid...),  the foundation will add another $200 to the bounty 
offered by Anthony Walter, subject to his and our approval.

Michael.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Operator not overloaded

2022-06-24 Thread Thomas Kurz via fpc-pascal
Thank you very much, declaring the operator within the record does indeed solve 
the issue.

Just to be sure in case I might need it some day: Does this mean, if I need 
e.g. a comparison operator for a specialized TPair, I would declare a record 
class helper and define the operator there?



- Original Message - 
From: Sven Barth via fpc-pascal 
To: FPC-Pascal users discussions 
Sent: Friday, June 24, 2022, 10:43:55
Subject: [fpc-pascal] Operator not overloaded

Thomas Kurz via fpc-pascal  schrieb am
Do., 23. Juni 2022, 19:45:

> When compiling, I get this error:

> pathfinding.pas(17,17) Error: Operator is not overloaded: "TTileSegment" =
> "TTileSegment"

> Which I don't understand -- because the "=" operator is defined in
> tesstypes.pas.

> Am I doing something wrong or is this behavior a bug?


Global operator overloads need to be available at the time the generic is
*declared*, not *specialized*. That is one of the reasons why advanced
records were introduced.

So you need to declare your operators as part of your record.

Regards,
Sven

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] Operator not overloaded

2022-06-23 Thread Thomas Kurz via fpc-pascal
Hello,

I have tried to create an example as minimalistic as possible. I have three 
files:

*** file: pathfinding.pas ***

unit PathFinding;

{$mode objfpc}

interface

type generic TAStar = class (TObject)
  public function FindPath (const AStart: T; const ADestination: T): Boolean; 
virtual;
end;

implementation

function TAStar.FindPath (const AStart: T; const ADestination: T): Boolean;
  var current: T;
  begin
current:=Default(T);
if (current = ADestination) then Exit (false);
  end;

end.

*** file: testtypes.pas ***

unit testTypes;

{$mode objfpc}

interface

type TTileSegment = record
  A: NativeUInt;
  B: NativeUInt;
end;

operator = (ALeft: TTileSegment; ARight: TTileSegment): Boolean;
operator < (ALeft: TTileSegment; ARight: TTileSegment): Boolean;
operator > (ALeft: TTileSegment; ARight: TTileSegment): Boolean;

implementation

operator = (ALeft: TTileSegment; ARight: TTileSegment): Boolean;
  begin
Exit (True);
  end;

operator < (ALeft: TTileSegment; ARight: TTileSegment): Boolean;
  begin
Exit (True);
  end;

operator > (ALeft: TTileSegment; ARight: TTileSegment): Boolean;
  begin
Exit (True);
  end;

end.

*** file: project1.lpr ***

program project1;

{$mode objfpc}

uses testtypes, PathFinding;

var x: specialize tastar;

begin
  x := specialize tastar.create;
end.

** 

When compiling, I get this error:

pathfinding.pas(17,17) Error: Operator is not overloaded: "TTileSegment" = 
"TTileSegment"

Which I don't understand -- because the "=" operator is defined in 
tesstypes.pas.

Am I doing something wrong or is this behavior a bug?

Kind regards,
Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] Functions for dealing with floating-point precision

2022-06-19 Thread Thomas Kurz via fpc-pascal
Hello,

in my program I have need for checking floating-point precision. I'm internally 
using floating-points for calculations, but in the end I have to use integer 
numbers. I cannot use Round() because I have to check for thresholds. I.e. that 
I wish to accept a value of 1. as being ">=2". As you can see, I cannot 
use Trunc() either, so I decided to check for the difference in ULPs (unit in 
the last place).

I couldn't find the corresponding functions in the RTL, but I think they should 
be included. I wrote the functions listed below. I would appreciate if the 
maintainers of FPC decide to add them to the Math unit. I skipped the functions 
for the Extended type, but if it's being desired, I can add hand them in later.

Kind regards,
Thomas


*** code:


const MAX_ULP_SINGLE = 2.028240960E+31;
const MAX_ULP_DOUBLE = 1.9958403095347198E+292;

function SingleToLongBits (Argument: Single): UInt32;
  begin
Move (Argument, Result, SizeOf(UInt32));
  end;

{$ifdef FPC_HAS_TYPE_DOUBLE}
function DoubleToLongBits (Argument: Double): UInt64;
  begin
Move (Argument, Result, SizeOf(UInt64));
  end;
{$endif FPC_HAS_TYPE_DOUBLE}

function LongBitsToSingle (Argument: UInt32): Single;
  begin
Move (Argument, Result, SizeOf(Single));
  end;

{$ifdef FPC_HAS_TYPE_DOUBLE}
function LongBitsToDouble (Argument: UInt64): Double;
  begin
Move (Argument, Result, SizeOf(Double));
  end;
{$endif FPC_HAS_TYPE_DOUBLE}

// returns the first floating-point argument with the sign of the second 
floating-point argument
function CopySign (x: Single; y: Single): Single;
  begin
Exit (Abs(x) * Sign(y));
  end;

{$ifdef FPC_HAS_TYPE_DOUBLE}
// returns the first floating-point argument with the sign of the second 
floating-point argument
function CopySign (x: Double; y: Double): Double;
  begin
Exit (Abs(x) * Sign(y));
  end;
{$endif FPC_HAS_TYPE_DOUBLE}

function IsSameSign (x: Single; y: Single): Boolean;
  begin
Exit (CopySign(x, y) = x);
  end;

{$ifdef FPC_HAS_TYPE_DOUBLE}
function IsSameSign (x: Double; y: Double): Boolean;
  begin
Exit (CopySign(x, y) = x);
  end;
{$endif FPC_HAS_TYPE_DOUBLE}

function NextAfter (Start: Single; Direction: Single): Single;
  var
absStart: Single;
absDir: Single;
toZero: Boolean;
  begin
// If either argument is a NaN, then NaN is returned.
if IsNan(Start) OR IsNan(Direction) then Exit (NaN);
// If both arguments compare as equal the second argument is returned.
if (Start = Direction) THEN Exit (Direction);
absStart := Abs(Start);
absDir := Abs(Direction);
toZero := NOT IsSameSign (Start, Direction) OR (AbsDir < absStart);
if (toZero) then begin
  // we are reducing the magnitude, going toward zero.
  if (absStart = MinSingle) then Exit (CopySign (0.0, Start));
  if IsInfinite(absStart) THEN Exit (CopySign (MaxSingle, Start));
  Exit (CopySign (LongBitsToSingle (Pred(SingleToLongBits(absStart))), 
Start));
end else begin
  // we are increasing the magnitude, toward +-Infinity
  if (Start = 0.0) then Exit (CopySign (MinSingle, Direction));
  if (absStart = MaxSingle) then Exit (CopySign (Infinity, Start));
  Exit (CopySign (LongBitsToSingle(Succ(SingleToLongBits(absStart))), 
Start));
end;
  end;

{$ifdef FPC_HAS_TYPE_DOUBLE}
function NextAfter (Start: Double; Direction: Double): Double;
  var
absStart: Double;
absDir: Double;
toZero: Boolean;
  begin
// If either argument is a NaN, then NaN is returned.
if IsNan(Start) OR IsNan(Direction) then Exit (NaN);
// If both arguments compare as equal the second argument is returned.
if (Start = Direction) THEN Exit (Direction);
absStart := Abs(Start);
absDir := Abs(Direction);
toZero := NOT IsSameSign (Start, Direction) OR (AbsDir < AbsStart);

if (toZero) then begin
  // we are reducing the magnitude, going toward zero.
  if (absStart = MinDouble) then Exit (CopySign (0.0, Start));
  if IsInfinite(absStart) THEN Exit (CopySign (MaxDouble, Start));
  Exit (CopySign (LongBitsToDouble (Pred(DoubleToLongBits(absStart))), 
Start));
end else begin
  // we are increasing the magnitude, toward +-Infinity
  if (Start = 0.0) then Exit (CopySign (MinDouble, Direction));
  if (AbsStart = MaxDouble) then Exit (CopySign (Infinity, Start));
  Exit (CopySign (LongBitsToDouble(Succ(DoubleToLongBits(absStart))), 
start));
end;
  end;
{$endif FPC_HAS_TYPE_DOUBLE}

function FloatPrior (Argument: Single): Single;
  begin
Exit (NextAfter (Argument, NegInfinity));
  end;

function FloatNext (Argument: Single): Single;
  begin
Exit (NextAfter (Argument, Infinity));
  end;

{$ifdef FPC_HAS_TYPE_DOUBLE}
function FloatPrior (Argument: Double): Double;
  begin
Exit (NextAfter (Argument, NegInfinity));
  end;
{$endif FPC_HAS_TYPE_DOUBLE}

{$ifdef FPC_HAS_TYPE_DOUBLE}
function FloatNext (Argument: Double): Double;
  begin
Exit (NextAfter (Argument, Infinity));
  

Re: [fpc-pascal] Feature Announcement: Function References and Anonymous Functions

2022-05-28 Thread Thomas Kurz via fpc-pascal
This is horrendous code, especially the last example. Looks like PHP or 
JavaScript, which I hate because their code is hard to read. I'm using pascal 
because I like its clean and easy-to-read syntax.

"-1" is a statement that should give a compiler error. "Result" and "Exit(x)" 
are established constructs and I don't see any need for changing, or even 
worse: omitting, them.

What should the data type of "left, right" be?

What should "@" mean?



- Original Message - 
From: Benito van der Zander via fpc-pascal 
To: fpc-pascal@lists.freepascal.org 
Sent: Saturday, May 28, 2022, 14:04:46
Subject: [fpc-pascal] Feature Announcement: Function References and Anonymous 
Functions

Hi,

> Sort((left, right) begin
>  if left < right then
>result := -1
>  else if left > right then
>result := 1
>  else
>result := 0;
>end);

One could introduce the @ operator to get a reference to a block of code.

Sort( @(left, right) begin
 if left < right then
   result := -1
 else if left > right then
   result := 1
 else
   result := 0;
   end);


The "result" variable is also ugly. You could make "if" an expression:

Sort( @(left, right) begin
 result :=
   if left < right then -1
   else if left > right then 1
   else 0;
   end);


Then the begin end could be removed too. Make @:= an operator to turn an 
expression to a function

Sort( @(left, right) :=
if left < right then -1
else if left > right then 1
else 0;
   );





Benito

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Feature Announcement: Function References and Anonymous Functions

2022-05-26 Thread Thomas Kurz via fpc-pascal
Great!!! Thank you very very much :)))


- Original Message - 
From: Sven Barth via fpc-pascal 
To: fpc-annou...@lists.freepascal.org 
Sent: Thursday, May 26, 2022, 21:47:06
Subject: [fpc-pascal] Feature Announcement: Function References and Anonymous 
Functions

Dear Free Pascal Community,

The Free Pascal Developer team is pleased to finally announce the 
addition of a long awaited feature, though to be precise it's two 
different, but very much related features: Function References and 
Anonymous Functions. These two features can be used independantly of 
each other, but their greatest power they unfold when used together.

These features are based on the work by Blaise.ru, so thank you very 
much and I hope you're doing well considering the current situation.

In the following we'll highlight both features separately and then we'll 
take a look at using them together.

= Function References =

Function References (also applicable names are Procedure References and 
Routine References, in the following only Function References will be 
used) are types that can take a function (or procedure or routine), 
method, function variable (or procedure variable or routine variable), 
method variable, nested function (or nested procedure or nested routine) 
or an anonymous function (or anonymous procedure or anonymous routine) 
as a value. The function reference can then be used to call the provided 
function just like other similar routine pointer types. In contrast to 
these other types nearly all function-like constructs can be assigned to 
it (the only exception are nested function variables (or nested 
procedure variables or nested routine variables), more about that later 
on) and then used or stored.

Function references are enabled with the modeswitch FUNCTIONREFERENCES 
(the following examples will assume that this modeswitch is provided).

A function reference is declared as follows:

REFERENCE TO FUNCTION|PROCEDURE [(argumentlist)][: resulttype;] 
[directives;]

Examples:

=== code begin ===

type
   TProcLongInt = reference to procedure(aArg: LongInt); stdcall;
   TFuncTObject = reference to function(aArg: TObject): TObject;

=== code end ===

Like other function pointer types function references can also be 
declared as generic:

=== code begin ===

type
   generic TGenericProc = reference to procedure(aArg: T);

=== code end ===

As you can see, once function references are enabled you can't use the 
identifier "REFERENCE" as part of an alias declaration without using "&":

=== code begin ===

type
   someref = reference; // will fail
   someref =  // correct fix

var
   somevar: reference; // will fail
   somevar:  // correct fix

=== code end ===

A function reference variable can then be called like any other function 
pointer type:

=== code begin ===

var
   p: TProcLongInt;
begin
   p := @SomeLongIntProc;
   p(42);
end.

=== code end ===

If a function reference has no parameters then you need to use "()" 
nevertheless in the FPC/ObjFPC modes like for other function pointer types:

=== code begin ===

type
   TProc = reference to procedure;
var
   p: TProc;
begin
   p := @SomeProcedure;
   p(); // required
   p; // this can be used e.g. in mode Delphi
end.

=== code end ===

Like other function pointer types they can also be declared anonymously 
as part of a variable, field declaration (but not as part of a paramater 
declaration):

=== code begin ===

var
   f: reference to function: LongInt;

type
   TTest = class
 f: reference to procedure;
   end;

=== code end ===

They get their great power from a point that is for once *not* 
considered an implementation detail: function references are in fact 
internally declared as reference counted interfaces with a single 
Invoke() method of the provided signature. So the above examples are in 
fact declared like this:

=== code begin ===

type
   TProcLongInt = interface(IInterface)
 procedure Invoke(aArg: LongInt); stdcall; overload;
   end;

   TFuncTObject = interface(IInterface)
 procedure Invoke(aArg: TObject): TObject; overload;
   end;

   generic TGenericProc = interface(IInterface)
 procedure Invoke(aArg: T); overload;
   end;

=== code end ===

This has a few implications:
- in the RTTI this will appear like a normal interface
- it reacts to the $M directive like a normal interface
- it is a managed type
- it has *no* valid GUID
- it can be implemented by a class
- it can be inherited from

Especially the last two points are important.

That the interface can be implemented means that much more functionality 
and state can be added to a function reference:

=== code begin ===

type
   TFunc = reference to function: LongInt;

   TSomeImpl = class(TInterfacedObject, TFunc)
 f: LongInt;
 function Invoke: LongInt;
   end;

function TSomeImpl.Invoke: LongInt;
begin
   Result := f;
end;

var
   t: TSomeImpl;
   f: TFunc;
begin
   t := TSomeImpl.Create;
   f := t;
   Writeln(f()); // will write 0
   t.f := 42;
   

[fpc-pascal] Strange "division by zero" error using variants

2022-05-24 Thread Thomas Kurz via fpc-pascal
Dear all,

please consider the following code:


program Project1;

{$booleval off}

var
  v1, v2: variant;
  a: boolean;
  b: integer;

begin
  a := true;
  b := 0;
  // this works as expected:
  if a and (b > 0) and ((0+1) mod b = 0) then Writeln ('ok');

  v1 := true;
  v2 := 0;
  // this gives a "division by zero":
  if v1 and (v2 > 0) and ((0+1) mod v2 = 0) then Writeln ('ok');
end.


The "variant" variant results in a "division by zero". Obviously, it tries to 
evaluate the modulo-expression even though this shouldn't happen because 
complete boolean evaluation is disabled and the "if"-result is already known to 
be false after checking "v2>0".

Can anyone explain this strange behavior?

Kind regards,
Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Correct way for using TThread.ForceQueue?

2022-04-25 Thread Thomas Kurz via fpc-pascal
EDIT: The code should be "TThread.ForceQueue", not "TThread.Synchronize"; I 
have corrected that.


I cannot remember why, but a long time ago when learning Delphi 5 or 6, I have 
learned not to call the destructor from within any method of the class, only 
from outside. If this is no longer true nowadays (or maybe, has never been true 
before), I'd like to use this solution.

Just to be sure we're talking about the same thing -- you think this code 
should work:

type
  TMyData = class 
method: TMethodWithParameters;
a: whatever;
procedure Run;
  end;
  
 procedure TMyData.Run;
   begin
 method (a);
 Self.Free;
   end;
   
 ...

MyData := TMyData.Create;
MyData.a := ...;
MyData.method := @SomeMethodWithParameters;
TThread.ForceQueue (NIL, @MyData.Run)



- Original Message - 
From: Michael Van Canneyt via fpc-pascal 
To: Thomas Kurz via fpc-pascal 
Sent: Monday, April 25, 2022, 16:58:26
Subject: [fpc-pascal] Correct way for using TThread.ForceQueue?



On Mon, 25 Apr 2022, Thomas Kurz via fpc-pascal wrote:

> This is a very elegant solution but it can only be used for Synchronize,
> right?  Because with ForceQueue I cannot know when it's done and freeing
> within Run (i.e.  "Self.Free") would fail.

Why would this fail according to you ?

I have used this approach on multiple occasions.

Michael.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Correct way for using TThread.ForceQueue?

2022-04-25 Thread Thomas Kurz via fpc-pascal
I cannot remember why, but a long time ago when learning Delphi 5 or 6, I have 
learned not to call the destructor from within any method of the class, only 
from outside. If this is no longer true nowadays (or maybe, has never been true 
before), I'd like to use this solution.

Just to be sure we're talking about the same thing -- you think this code 
should work:

type
  TMyData = class 
method: TMethodWithParameters;
a: whatever;
procedure Run;
  end;
  
 procedure TMyData.Run;
   begin
 method (a);
 Self.Free;
   end;
   
 ...

MyData := TMyData.Create;
MyData.a := ...;
MyData.method := @SomeMethodWithParameters;
TThread.Synchronize(NIL, @MyData.Run)



- Original Message - 
From: Michael Van Canneyt via fpc-pascal 
To: Thomas Kurz via fpc-pascal 
Sent: Monday, April 25, 2022, 16:58:26
Subject: [fpc-pascal] Correct way for using TThread.ForceQueue?



On Mon, 25 Apr 2022, Thomas Kurz via fpc-pascal wrote:

> This is a very elegant solution but it can only be used for Synchronize,
> right?  Because with ForceQueue I cannot know when it's done and freeing
> within Run (i.e.  "Self.Free") would fail.

Why would this fail according to you ?

I have used this approach on multiple occasions.

Michael.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Correct way for using TThread.ForceQueue?

2022-04-25 Thread Thomas Kurz via fpc-pascal
This is a very elegant solution but it can only be used for Synchronize, right? 
Because with ForceQueue I cannot know when it's done and freeing within Run 
(i.e. "Self.Free") would fail.

Using an advanced record would be fine, but it doesn't fit the declaration 
"TThreadMethod = procedure of object".



- Original Message - 
From: Mattias Gaertner via fpc-pascal 
To: fpc-pascal@lists.freepascal.org 
Sent: Monday, April 25, 2022, 16:12:40
Subject: [fpc-pascal] Correct way for using TThread.ForceQueue?

On Mon, 25 Apr 2022 15:47:57 +0200
Thomas Kurz via fpc-pascal  wrote:

>[...]
> As far as I have seen so far, the common solution is to use a
> variable inside the class to cache the parameters, then to use a
> DoCallSync procedure which takes no parameters but can use the cached
> values inside, and finally to call TThread.Synchronize(NIL,
> @DoCallSync). I have stick to this concept when using Synchronize,
> too.

Or some small class:

type
  TMyData = class 
a: whatever;
procedure Run;
  end;

MyData:=TMyData.Create;
MyData.a:=...;
TThread.Synchronize(NIL, @MyData.Run).

Free MyData when done and/or in the destructor.

 
>[...]

Mattias
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] Correct way for using TThread.ForceQueue?

2022-04-25 Thread Thomas Kurz via fpc-pascal
Hello,

my question is about using the TThread.Synchronize, Queue and ForceQueue 
methods. Unfortunately, the parameter they take is of type TThreadMethods which 
allows calling only methods having no parameters at all. I assume this is done 
to simplify the implementation on client-side but causes headaches on my side :)

Delphi solves the issue with having anonymous methods which aren't yet 
available in FPC yet. So unfortunately I cannot do something like 
TThread.Synchronize(NIL, @procedure(a,b,c)).

As far as I have seen so far, the common solution is to use a variable inside 
the class to cache the parameters, then to use a DoCallSync procedure which 
takes no parameters but can use the cached values inside, and finally to call 
TThread.Synchronize(NIL, @DoCallSync). I have stick to this concept when using 
Synchronize, too.

But what is the correct way to deal with ForceQueue? I think I cannot use a 
global variable for this case because its value could be overwritten between 
the call to ForceQueue and the moment the queued method is actually being run. 
Do I have to use a FIFO-buffer for this purpose? And if yes, would it be safe 
(in the sense of getting no deadlock situations) to use a TThreadList for that?

Kind regards,
Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] Possible fpdebug issue

2022-04-23 Thread Thomas Kurz via fpc-pascal
Dear all,

I'm not sure whether or not this is an issue with fpdebug, so I'd like to 
describe it here first:

I have a main program (Win32 GUI running on Win 8.1) which loads and unloads a 
DLL dynamically. I know that fpdebug is currently not able to debug DLLs, but 
imho I don't do so, but the issue might be related.

The program runs fine when being run without debugger or when using GDB. 
However, a crash occurs when fpdebug is active and the call to "FreeLibrary" is 
made. The error is:

Project raised exception class 'External: Unknown exception code
$E0465043'. At address 76EB56E8.

The DLL is my own and I tried to debug the Finalization section with GDB, but I 
cannot find an issue there. So imho unloading the DLL should not cause any 
trouble. As I said, I'm not trying to actually step into the DLL; I'm only 
using fpdebug in the main program and trying to step over the "FreeLibrary" 
line.

Kind regards,
Thomas

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Feature announcement: implicit generic function specializations

2022-04-23 Thread Thomas Kurz via fpc-pascal
Thank you for continuously enhancing Free Pascal. Happy to see every new 
feature :)

Is there any work ongoing about overloaded properties? E.g.

property x: integer read GetX;
property x[aindex: integer]: integer write SetX;

I know that declaring the property only once and overloading the getters and 
setters work, but sometimes I wish to have different read/readwrite/write 
access for overloaded properties and this is not possible at the moment. 
Furthermore, code completion in Lazarus doesn't show the different parameters 
of overloaded properties.


- Original Message - 
From: Sven Barth via fpc-pascal 
To: fpc-annou...@lists.freepascal.org 
Sent: Wednesday, April 20, 2022, 19:15:15
Subject: [fpc-pascal] Feature announcement: implicit generic function 
specializations

Dear FPC community,

The FPC developers are pleased to announce the implementation of a new 
feature: implicit generic function specializations. This feature was 
implemented by Ryan Joseph, so thank you very much, Ryan.

This feature allows you to use generic routines (functions, procedures, 
methods) without explicitely specializing them (“<…>” in Delphi modes 
and “specialize …<…>” in non-Delphi modes) as long as the compiler can 
determine the correct parameter types for the generic.

This feature is enabled with the modeswitch 
ImplicitFunctionSpecialization and is for now not enabled by default as 
this has the potential to break existing code.

Assume you have the following function:

=== code begin ===

generic function Add(aArg1, aArg2: T): T;
begin
   Result := aArg1 + aArg2;
end;

=== code end ===

Up to now you could only use this function as follows:

=== code begin ===

SomeStr := specialize Add('Hello', 'World');
SomeInt := specialize Add(2, 5);

=== code end ===

However with implicit function specializations enabled you can also use 
it as follows:

=== code begin ===

SomeStr := Add('Hello', 'World');
SomeInt := Add(2, 5);

=== code end ===

The compiler will automatically determine the type of the generic 
parameters based on the parameters you pass in (this is always done left 
to right). Depending on the passed in parameters (especially if you're 
using constant values like in the example instead of variables) the 
compiler might however pick a different type than you expected. You can 
enforce a specific type by either explicitely specializing the method as 
before or by inserting a type cast. In the example above the compile 
will specialize the call with the parameters “2, 5” using an 8-bit 
signed type (Pascal prefers signed types) instead of a LongInt as in the 
explicit specialization. If you use “LongInt(2), 5” as parameters then 
the compiler will pick that instead, however with “2, LongInt(5)” it 
will still pick an 8-bit type, because the parameter types are 
determined left to right.

If there exists a non-generic overload for which the parameters types 
match exactly, the compiler will pick that instead of specializing 
something anew. So assume you also have the following function in scope:

=== code begin ===

function Add(aArg1, aArg2: LongInt): LongInt;
begin
   Result := aArg1 + aArg2;
end;

=== code end ===

In the case of “Add(2, 5)” the compiler will *not* pick the non-generic 
function, because it determines that an 8-bit type is enough, however if 
you use “Add(LongInt(2), 5)” the compiler will pick the non-generic 
function.

Aside from simple parameters the compiler also supports arrays and 
function/method variables:

=== code begin ===

generic function ArrayFunc(aArg: specialize TArray): T;
var
   e: T;
begin
   Result := Default(T);
   for e in aArg do
 Result := Result + e;
end;

type
   generic TTest = function(aArg: T): T;

generic function Apply(aFunc: specialize TTest; aArg: T): T;
begin
   Result := aFunc(aArg);
end;

function StrFunc(aArg: String): String;
begin
   Result := UpCase(aArg);
end;

function NegFunc(aArg: LongInt): LongInt;
begin
   Result := - aArg;
end;

begin
   Writeln(ArrayFunc([1, 2, 3])); // will write 6
   Writeln(ArrayFunc(['Hello', 'FPC', 'World'])); // will write 
HelloFPCWorld

   Writeln(Apply(@StrFunc, 'Foobar')); // will write FOOBAR
   Writeln(Apply(@NegFunc, 42)); // will write -42
end.

=== code end ===

There are of course a few restrictions for this feature:
- all generic parameters must be used in the declaration of the routine 
(implementation only type parameters are not allowed)
- all parameters that have a generic type must not be default 
parameters, they need to be used in the call or their type must have 
been fixed by a parameter further left (as currently default values for 
parameters of a generic type are not supported this is not much of a 
restriction, but should that change (e.g. Default(T)) then this 
restriction will apply)
- the generic routine must not have constant generic parameters (this 
might be extended in the future with e.g. static arrays or file types, 
but for now this restriction stands)
- the result type 

Re: [fpc-pascal] Caller agnostic procedure variables

2022-02-15 Thread Thomas Kurz via fpc-pascal
> The "Reference to procedure" that will be part of anonymous functionswill do 
> this for you.

What release are anonymous functions planed for? FPC 3.4.0?

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] Strange behavior in generics.collections TDictionary

2022-01-26 Thread Thomas Kurz via fpc-pascal
Consider the following code:

***
PROGRAM project1;

{$mode objfpc}
{$longstrings on} // see output below
{$modeswitch advancedrecords}

USES Variants, Generics.Collections, SysUtils;

TYPE TRecord = PACKED RECORD
  FID: NativeUInt;
  FKey: String;
  CONSTRUCTOR Create (AID: NativeUInt; AKey: String);
END;

CONSTRUCTOR TRecord.Create (AID: NativeUInt; AKey: String);
BEGIN
  FID := AID;
  FKey := UpperCase (AKey);
END;

VAR
  Dict: SPECIALIZE TDictionary;
  i: SPECIALIZE TPair;

BEGIN
  Dict := SPECIALIZE TDictionary.Create;
  Dict.Add (TRecord.Create (1, 'test'), 1);
  FOR i IN Dict DO Writeln (i.Key.FID, #9, i.Key.FKey, #9, i.Value);
  // ^^^ 1 TEST 1
  // -> so the entry is ok!
  Writeln (Dict.ContainsKey (TRecord.Create (1, 'test')));
  // ^^^ with longstrings on -> FALSE
  // with longstrings off -> TRUE
  Writeln (Dict.ContainsKey (TRecord.Create (1, 'TEST')));
  // ^^^ always FALSE
  Dict.Free;
END.
***

I'm very confused... I have no idea if I'm overseeing something or this is a 
bug in generics.collections or in the compiler.

My system is:
Lazarus 2.2.0 (64 bit), FPC 3.2.2 (64 bit) on Windows 8.1 (64 bit)

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal