Re: [fpc-pascal] Can FPC optimize: if (s[i]='a') or ...

2019-04-14 Thread Tomas Hajny
On Mon, April 15, 2019 07:52, Bernd Oppolzer wrote:
 .
 .
>>> On Samstag, 13. April 2019 22:30:55 CEST Alexey Tor. wrote:
 .
 .
 Can FPC optimize it so it only reads s[i] once (to register), not 3
 times?
 .
 .
> True for New Stanford Pascal:
 .
 .

I fail to see how is this related to FPC or the question of the original
poster (who was explicitly asking about FPC). Could we stay on topic,
please?

Tomas
(one of FPC mailing list moderators)


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

Re: [fpc-pascal] Can FPC optimize: if (s[i]='a') or ...

2019-04-14 Thread Bernd Oppolzer

Am 15.04.2019 um 03:35 schrieb wkitt...@windstream.net:

On 4/14/19 7:28 AM, Rainer Stratmann wrote:

On Samstag, 13. April 2019 22:30:55 CEST Alexey Tor. wrote:

E.g. i have a loop which test each s[i] char for several cases: 'a',
'b', 'c'.

for i:= 1 to length(s) do

if (s[i]='a') or (s[i]='b') or (s[i]='c') then ...

Can FPC optimize it so it only reads s[i] once (to register), not 3 
times?


You can optimise by yourself.

var
  c : char;
  l : longint;

begin
  l := length( s );
  for i := 1 to l do
   c := s[ i ];
   if ( c = 'a' ) or ( c = 'b' ) or ( c = 'c' ) then ...



this looks like it will read three times like the original instead of 
once like using the IN set operation... it is still stepping through 
each one of the comparison steps instead of just doing a set match...





True for New Stanford Pascal:

 23   1N   1)    for I := 1 to LENGTH ( S ) do
 24   2N   1)  begin
 25   2N   1)    C := S [ I ] ;
 26   2N   1)    if ( C = 'a' ) or ( C = 'b' ) or ( C = 'c' 
) then
 27   2N   1)  WRITELN ( I , '-tes Zeichen ist a, b 
oder c' ) ;

 28   2N   1)  end (* for *)

Lines without @@ = P-Code
Lines with @@ = IBM 370 Machine Code (Assembler notation)
as documented by Stage 2 (PASCAL2.PAS) when the A+ switch is set

 LOC  26 
 0250:   LOD  C,1,424
 0250:   LDC  C,'a'
 0250:   EQU  C
@@ 0250:   CLI   424(13),97  --- compare storage location with 'a'
 0254:   LOD  C,1,424
@@ 0254:   LA    2,1
@@ 0258:   BC    8,*+6
@@ 025C:   SR    2,2
 025E:   LDC  C,'b'
 025E:   EQU  C
@@ 025E:   CLI   424(13),98  --- compare storage location with 'b'
 0262:   IOR  B
@@ 0262:   LA    3,1
@@ 0266:   BC    8,*+6
@@ 026A:   SR    3,3
@@ 026C:   OR    2,3
 026E:   LOD  C,1,424
 026E:   LDC  C,'c'
 026E:   EQU  C
@@ 026E:   CLI   424(13),99  --- compare storage location with 'c'
 0272:   IOR  B
@@ 0272:   LA    3,1
@@ 0276:   BC    8,*+6
@@ 027A:   SR    3,3
@@ 027C:   OR    2,3
 027E:   FJP  L16
@@ 027E:   BC    8,L16


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

Re: [fpc-pascal] mode switch madness

2019-04-14 Thread wkitty42

On 4/14/19 9:08 AM, Anthony Walter wrote:

Someone said:

"You can do a {$i mysettings.inc}"

I give that a +1



FWIW: all of the delphi code that i've worked with trying to port to FPC has had 
this... at least one had an include file that IFDEF'd its way through like 4 or 
5 other pascal compilers... to me, once i saw this and realized what it was 
doing, this seems like the best way and also to be the pascal way...



--
 NOTE: No off-list assistance is given without prior approval.
   *Please keep mailing list traffic on the list unless*
   *a signed and pre-paid contract is in effect with us.*
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] Can FPC optimize: if (s[i]='a') or ...

2019-04-14 Thread wkitty42

On 4/14/19 7:28 AM, Rainer Stratmann wrote:

On Samstag, 13. April 2019 22:30:55 CEST Alexey Tor. wrote:

E.g. i have a loop which test each s[i] char for several cases: 'a',
'b', 'c'.

for i:= 1 to length(s) do

if (s[i]='a') or (s[i]='b') or (s[i]='c') then ...

Can FPC optimize it so it only reads s[i] once (to register), not 3 times?


You can optimise by yourself.

var
  c : char;
  l : longint;

begin
  l := length( s );
  for i := 1 to l do
   c := s[ i ];
   if ( c = 'a' ) or ( c = 'b' ) or ( c = 'c' ) then ...



this looks like it will read three times like the original instead of once like 
using the IN set operation... it is still stepping through each one of the 
comparison steps instead of just doing a set match...



--
 NOTE: No off-list assistance is given without prior approval.
   *Please keep mailing list traffic on the list unless*
   *a signed and pre-paid contract is in effect with us.*
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] Optional param modifier

2019-04-14 Thread Martin Frb

On 15/04/2019 01:19, Ryan Joseph wrote:



On Apr 14, 2019, at 7:08 PM, Martin Frb  wrote:

Almost. assert takes the condition itself

assert(condition_that_must_be_true, 'error message')

so it would be
   assert(name<>'', 'requires "name <> " failed for CreateHero');

You can already insert such asserts yourself. assert exists.

If you compile with -Sa then they are compiled in the code, otherwise not.

 From the compilers perspective isn’t it faster to test the condition first in 
an if statement so the assert function doesn’t get called? Assert tests for 
false also so it needs to invert the test to “name = ‘’” which is not how the 
“requires” statement is worded.

I’ve always made a “fatal” function which works in the opposite direction as 
assert, i.e if the condition is *true* then crash. Don’t know why but that’s 
easier for me to understand. I like the requires section because it works in 
the same logic.


You had

requires
  name <> '';

Or in other words: bail if name = ''

  assert(name<>'', ...)
does that.
It bails if name = ''. (then the condition "name <> '' " would be false 
=> bail)


requires, like assert want the condition(s) to be true

Assert is for testing, so speed doesn't matter.
I don't know how it is internally implemented.

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

Re: [fpc-pascal] Optional param modifier

2019-04-14 Thread Ryan Joseph


> On Apr 14, 2019, at 7:08 PM, Martin Frb  wrote:
> 
> Almost. assert takes the condition itself
> 
> assert(condition_that_must_be_true, 'error message')
> 
> so it would be
>   assert(name<>'', 'requires "name <> " failed for CreateHero');
> 
> You can already insert such asserts yourself. assert exists.
> 
> If you compile with -Sa then they are compiled in the code, otherwise not.

From the compilers perspective isn’t it faster to test the condition first in 
an if statement so the assert function doesn’t get called? Assert tests for 
false also so it needs to invert the test to “name = ‘’” which is not how the 
“requires” statement is worded.

I’ve always made a “fatal” function which works in the opposite direction as 
assert, i.e if the condition is *true* then crash. Don’t know why but that’s 
easier for me to understand. I like the requires section because it works in 
the same logic.


Regards,
Ryan Joseph

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

Re: [fpc-pascal] Optional param modifier

2019-04-14 Thread Martin Frb

On 15/04/2019 00:53, Ryan Joseph wrote:


Here’s what I imagine that would look like:

procedure CreateHero (name: string; hp: integer);
requires
   name <> '';
   (hp > 0) and (hp < 100);
begin
   // compilers parses the conditions and inserts as if statements:
   // if name <> ‘’ then
   //   assert(‘condition "name <> ‘'" for CreateHero failed’);
   // if (hp > 0) and (hp < 100) then
   //   assert(‘condition "(hp > 0) and (hp < 100)" for CreateHero failed);
end;




Almost. assert takes the condition itself

assert(condition_that_must_be_true, 'error message')

so it would be
  assert(name<>'', 'requires "name <> " failed for CreateHero');

You can already insert such asserts yourself. assert exists.

If you compile with -Sa then they are compiled in the code, otherwise not.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] Optional param modifier

2019-04-14 Thread Ryan Joseph


> On Apr 14, 2019, at 6:30 PM, Martin Frb  wrote:
> 
> I would actually argue that it is infinitely more important to check for nil 
> after MakeThing. (Unless I know for sure it is not needed: proof, docs)
> 
> Assuming (taking the danger of doing so) both do what there name indicates, 
> then:
> - If I forget to check after FindThing, it is likely to cause an error very 
> soon, and most probably while I am testing myself.
> - If I forget it after MakeThing, it may be very rare to cause an error. It 
> will likely pass my tests, and cause a customer of mine some stress.

I understand all your concerns over not wanting to use this so I would suggest 
to avoid it (we all feel that way about certain features). Since no-one thinks 
this is a good idea I’ll forget about because it’s not that important anyways. 
Waiting for nullable types is maybe a better option anyways and those are in 
the pipeline via default properties. 

What Sven brought up is more immediately useful anyways and I can think of many 
times I have the mandatory top part of the function that checks to make sure 
parameters are valid. Formalizing this process would be a smart thing I think. 
If you don’t agree, then don’t use it. ;)

That’s what I read from the link posted. As for the “ensure” block now that I 
don’t see as a pattern that I can recognize. Any real world examples of this? 

Here’s what I imagine that would look like:

procedure CreateHero (name: string; hp: integer);
requires
  name <> '';
  (hp > 0) and (hp < 100); 
begin
  // compilers parses the conditions and inserts as if statements:
  // if name <> ‘’ then
  //   assert(‘condition "name <> ‘'" for CreateHero failed’);
  // if (hp > 0) and (hp < 100) then
  //   assert(‘condition "(hp > 0) and (hp < 100)" for CreateHero failed);
end;

Pretty simple right?

Regards,
Ryan Joseph

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

Re: [fpc-pascal] Optional param modifier

2019-04-14 Thread Martin Frb

On 14/04/2019 22:08, Ryan Joseph wrote:

function FindThing: TThing; optional;

means you MUST check for nil. If the value is nil that’s not an error. 
“optional” is probably a bad name for this I know.

function MakeThing: TThing;

this means maybe check for nil or maybe not check for nil. We don’t know what 
the programmer intended because no extra information was given (at least in the 
declaration). Because of the name we probably assume this is going to return a 
new object which is safe so checking for nil would be a waste.


I would actually argue that it is infinitely more important to check for 
nil after MakeThing. (Unless I know for sure it is not needed: proof, docs)


Assuming (taking the danger of doing so) both do what there name 
indicates, then:
- If I forget to check after FindThing, it is likely to cause an error 
very soon, and most probably while I am testing myself.
- If I forget it after MakeThing, it may be very rare to cause an error. 
It will likely pass my tests, and cause a customer of mine some stress.



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

Re: [fpc-pascal] Optional param modifier

2019-04-14 Thread Martin Frb

On 14/04/2019 23:48, Martin Frb wrote:


I admit the contract/assert stuff may have made it seem different. But 
that is because this approach does not hold up (IMHO). And therefore 
the closest alternative was presented.


In the very end it is to avoid crashing on nil de-ref. And the 
contract/assert can help there. Though in a completely different way.


The contract actually can lead to the thing you want. Though you need to 
complete it for *all* your code, rather than just one or two functions


If/Once you have your entire code base with contracts, you know that any 
method/function that does not have a "assigned" contract, can return nil 
(i.e. nil is a documented expected return value / or input )


So at that time, you can enable a compiler warning of the kind you 
wanted. It would act on all the params/results that per contract can be 
nil (are not forbidden to be nil).


-
The only thing you do not have, is the undefined bit. The it can return 
nil, but I do not want to check it.
If you really want that, there will be a directive like {$PUSH}{$R-} 
 {$POP}.

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

Re: [fpc-pascal] Optional param modifier

2019-04-14 Thread Martin Frb

On 14/04/2019 22:08, Ryan Joseph wrote:


Per my example, currently we know that GetThing() COULD return nil so unless we 
know what the function does by reading the documentation or looking at the 
implementation we need to test for nil. Right? I suggest the modifier simply to 
enforce that check and let it be known that’s the desired usage.
I do get what you want. But not why (the personal why I get, the 
objective one not).
Or not what sense is it makes... Where again I get your description, but 
it seems arbitrary/randomly picked.
Sure perfectly fine on the few examples you gave. But then by that 
measure others will bring their examples (and believe me they will, and 
it will be examples neither of us would be able to derive today). And 
then we need further rules/modifiers/dedicated-checks for whatever 
examples they bring up...


As you wrote: "we need to test for nil"
Yes, and we need to do that for all of them. Even if they are not marked 
as "expect-me-to-be-nil". Because even if they are not marked, they 
still can be.


That means if we start warning in selected cases (the ones that are 
marked), then we give the user **false security** over all other cases. 
(I did not get a warning, so why does it crash on a nil-deref?)


The only place where we do not need to check for nil, is if we know it 
can not be nil.

We can gain that knowledge from 1 of 2 places
- some sort of modifier to the type declaration - or some sort of 
class-contract

- the docs

We can NOT get it from code review. Code may change, and then all the 
depended code becomes wrong. (It may be that the code should return nil, 
but due to a bug the current implementation does not)



So, in other words:

function FindThing: TThing; optional;

means you MUST check for nil. If the value is nil that’s not an error. 
“optional” is probably a bad name for this I know.

Don't worry about the name.

How does the compiler know that I have checked. Code can be arbitrarily 
complex. There will always be code that does check, but the compiler can 
not tell (heck I may have a checkAssigned procedure in assembler).
So at best the compiler can warn during compilation, but never give an 
error.



function MakeThing: TThing;

this means maybe check for nil or maybe not check for nil. We don’t know what 
the programmer intended because no extra information was given (at least in the 
declaration). Because of the name we probably assume this is going to return a 
new object which is safe so checking for nil would be a waste.

What if it run out of memory? And catches the exception.
Checking for nil is never a waste. Unless you have proof (in the 
mathematical sense) that nil can not happen.
Or if your rules allow you to trust the docs, and the docs say you can 
relay on it.



  But we don’t know that except for what the name implies or if we read the 
code.
Neither name, nor implementation are a reliable source for that info. 
See above.



Is that more clear? If there’s a better way to express this then please let me 
know.

Its been perfectly clear from (almost) the start.

I admit the contract/assert stuff may have made it seem different. But 
that is because this approach does not hold up (IMHO). And therefore the 
closest alternative was presented.


In the very end it is to avoid crashing on nil de-ref. And the 
contract/assert can help there. Though in a completely different way.



For parameters I like what Sven suggested to have a “requires” section 
in functions to check this but wouldn’t it make sense if the function 
parameter gave some hint also? “can be nil” or “can’t be nil” would 
both be helpful in terms of documentation and compile time errors 
instead of runtime errors. 


The pre-condition (requires) would have the same amount of compile time 
checks (and the remainder runtime) as a keyword like notnil or maybenil. 
In the same way range checks and others go part compile, part runtime.


As for "documentation". I disagree with the way it is done in oxygen. 
But I am not sure I have any good alternative.

For me a class contract (require/ensure) is part of the interface.

So it would have to be like (and similar for plain procedures, no class) 
// can be all on one line


type
  TFoo= class
 function DoTheFooThing(Foo1, Foo2: TFoo): Tbar;
    requires
   assigned(Foo1) or assigned(Foo2): 'Need at least 1 foo, for 
the connection';

    guarantees // better than ensure
   assigned(result);
   result.KnowsMyFoo = true: 'Connection exists';  // the =true 
is redundant

    procedure DoTheBar;
  end;

So reading this declaration, you immediately know what is valid. And if 
custom messages are give, they may tell you way


It is to be noted, that requires and guarantees contain conditions 
(expressions), not pascal code. So technically it is ok, that they are 
in the interface and not implementation.
If I want something in the implementation, I can use normal "assert" 
(which

[fpc-pascal] how to call .so library while using FREE Pascal JVM and Android target

2019-04-14 Thread Mgr. Janusz Chmiel

Dear specialists,
	Is it possible to call .so library when I have used Free Pascal 
compiler and I have set JVM target and option to create Android 
compatible Java classes?
Because when ever I want to call some .so library I Am getting The 
following error.

Failed resolution of: .so
OK
Sure, run-time error always contain full .so library name.
Is there any way to call .so libraryes or unfortunately it is not possible?
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] Optional param modifier

2019-04-14 Thread Ryan Joseph


> On Apr 14, 2019, at 3:38 PM, Martin Frb  wrote:
> 
> 
> One thing is what checks can be done, to help the programmer not to 
> accidentality  de-ref nil.
> The other thing is how.
> 
> 1) The "optional" is actually the default. If anything towards a deref-warn 
> feature was done, then *every* parameter,  *every* return-value (and even 
> every other var) of a nil-able type should be seen as optional.
> If a type is not optional, then it should be declared as "not nil-able" => 
> function foo(notnil a: TObject): notnil TOBject;

I read through but I think we’re stuck on this first misunderstanding. This is 
not the default, I would never suggest this since as you mentioned it leads to 
massive overreach. Never would I want this added to *every” param and return. 
Just to get that out of the way. Swift has done this and it SUCKS that we’re 
forced to unwrap optionals all the time. It’s so much friction and I really 
hate it.

I’m also not suggesting this means “not nil” either. I mean simply *may* be nil 
so you need to check. I know that all pointer types COULD be nil.

Per my example, currently we know that GetThing() COULD return nil so unless we 
know what the function does by reading the documentation or looking at the 
implementation we need to test for nil. Right? I suggest the modifier simply to 
enforce that check and let it be known that’s the desired usage.

So, in other words:

function FindThing: TThing; optional;

means you MUST check for nil. If the value is nil that’s not an error. 
“optional” is probably a bad name for this I know.

function MakeThing: TThing;

this means maybe check for nil or maybe not check for nil. We don’t know what 
the programmer intended because no extra information was given (at least in the 
declaration). Because of the name we probably assume this is going to return a 
new object which is safe so checking for nil would be a waste. But we don’t 
know that except for what the name implies or if we read the code.

Is that more clear? If there’s a better way to express this then please let me 
know.

> 
> That is in the same way as range checks. There is on "type x=array[1..50] 
> with range checks of integer;"
> 
> Using your "Optional" is just specifying what already applies. In other 
> words: redundant.
> 
> Now specifying it for a result, is different than specifying it for a 
> parameter.
> - For a parameter, the problem was:
>that if I want the compiler to check that I test for "assigned",
>=> then I must remember that I want the compiler to do that,
>=> because if I do not remember, then I would not add the "optional"
>   But:
>   If I already remember that I want to have a check for "assigned", then I 
> can do it right away.
>   I do not need the "optional", so that I get a warning for forgetting 
> something that I actually just though of.
> 

For parameters I like what Sven suggested to have a “requires” section in 
functions to check this but wouldn’t it make sense if the function parameter 
gave some hint also? “can be nil” or “can’t be nil” would both be helpful in 
terms of documentation and compile time errors instead of runtime errors.


Regards,
Ryan Joseph

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

Re: [fpc-pascal] Optional param modifier

2019-04-14 Thread Martin Frb

On 14/04/2019 19:53, Ryan Joseph wrote:



On Apr 14, 2019, at 1:38 PM, Sven Barth via fpc-pascal 
 wrote:

As already said by Martin: the compiler *can not* determine all cases whether 
the parameter is Nil or not, so it *must* be done at runtime to ensure this. 
Otherwise the feature is just as useful as this:

I’ve read over what Martin said and honestly I’m confused now. :) I’m not sure 
if I don’t understand you guys or you don’t understand me.

Lets use the example of the optional (i.e. "could be nil") return value because 
it’s most easy to understand. Why can’t the compiler know that the result of GetThing is 
an optional and therefore you *must* always check any code that dereferences it? Isn’t 
this a compile time issue?

In the example below I would always check for not nil if the documentation said 
it may be nil so why can’t the compiler just make you do that anyways and 
provide the information right there in the declaration? I don’t understand 
where the runtime element of this is.

function GetThing: TThing; optional;

var
   thing: TThing;
begin
   thing := GetThing;
   if assigned(thing) then
 writeln(thing.name);


Well the answer has several parts.

One thing is what checks can be done, to help the programmer not to 
accidentality  de-ref nil.

The other thing is how.

1) The "optional" is actually the default. If anything towards a 
deref-warn feature was done, then *every* parameter,  *every* 
return-value (and even every other var) of a nil-able type should be 
seen as optional.
If a type is not optional, then it should be declared as "not nil-able" 
=> function foo(notnil a: TObject): notnil TOBject;


That is in the same way as range checks. There is on "type 
x=array[1..50] with range checks of integer;"


Using your "Optional" is just specifying what already applies. In other 
words: redundant.


Now specifying it for a result, is different than specifying it for a 
parameter.

- For a parameter, the problem was:
   that if I want the compiler to check that I test for "assigned",
   => then I must remember that I want the compiler to do that,
   => because if I do not remember, then I would not add the "optional"
  But:
  If I already remember that I want to have a check for "assigned", 
then I can do it right away.
  I do not need the "optional", so that I get a warning for forgetting 
something that I actually just though of.


As something applied to the result, the reminder is for some other 
person. The person that will write the code.

Now that idea is perfectly fine.
- But the "optional" still is not. The user, the compiler, everyone 
already knows that the result can be nil. Every TObject can be nil. This 
is the default.
- So to improve this we would need a way to say: It will never be nil. 
(I.e., it is different from the default)
If we had that, then there would be nothing wrong with the compiler 
giving a hint, in case the user does not check.


So that is about the how.
- Reverse the spec, so it acknowledges the current default.
- Then issue warnings for every parameter or return value, that has not 
been marked as non-nil.


2) If the compiler does check, we have to consider that all current code 
defaults to nil-able.

To avoid floods of warnings the check would need to be off by default.
It could be enabled by
- directive
- command line to the compiler
- fpc.cfg

3) If the compiler does check, it can issue (at compile time) hints, 
notes, or in very very few cases warnings.
You can use -we to tread them as error, but they can never be error by 
default.


Code can be very complex. The compiler can never understand all possible 
ways of implementation. Therefore the compiler will always have false 
positives.
If those were errors by default, then perfectly valid code could not be 
compiled.

So hints, notes, and occasional warnings.

4) runtime checks:
Are entirely independent of the above.

However they can be helpful. They would work exactly like range-check 
errors work today.
If you declare a function can never return nil, then the compiler can 
(as a separate feature, with its own option) in addition to the 
hints/notes at compile time, add checks at runtime.


You do not write try except for range checks (at least that is not what 
range checks are meant for), and you would not do that for nil checks.


---
In conclusion:

The nil-deref-protection would be very much like range checks. (except 
that the nature of tracing the nil value is more complex, meaning you 
get notes instead of errors)


range checks can occur at compile time SomeString[-1] should give a 
compile time error (in that case actually an error)

range checks also occur at runtime.

nil-deref-protection  does the same.
It applies to *ALL* nil-able types by default.

In order to be useful it is necessary that the programmer has a way to 
tell the complier that variable/param/returnval do not fall into the 
default, and that they are never nil.



Invalid contracts are an e

Re: [fpc-pascal] mode switch madness

2019-04-14 Thread Ryan Joseph


> On Apr 14, 2019, at 1:29 PM, Sven Barth via fpc-pascal 
>  wrote:
> 
>> I like what Jonas did for the ObjC mode switch where he named them with 
>> versions. Maybe a {$mode objfpc2} one day.
> My idea was to maybe add a mode ObjFPCExt or ObjFPCAdv which is quite a bit 
> less conservative and might break backwards compatibility a bit more often 
> when new features are added.

That’s a good idea to make a place we can add new mode switches for new 
language features which 99% of people are going to use. Most mode switches 
don’t break backwards compatibility but the pending multi-helpers could 
certainly cause some problems. Array operators could also but can’t think of 
any others.

Regards,
Ryan Joseph

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

Re: [fpc-pascal] Optional param modifier

2019-04-14 Thread Ryan Joseph


> On Apr 14, 2019, at 1:38 PM, Sven Barth via fpc-pascal 
>  wrote:
> 
> As already said by Martin: the compiler *can not* determine all cases whether 
> the parameter is Nil or not, so it *must* be done at runtime to ensure this. 
> Otherwise the feature is just as useful as this:

I’ve read over what Martin said and honestly I’m confused now. :) I’m not sure 
if I don’t understand you guys or you don’t understand me.

Lets use the example of the optional (i.e. "could be nil") return value because 
it’s most easy to understand. Why can’t the compiler know that the result of 
GetThing is an optional and therefore you *must* always check any code that 
dereferences it? Isn’t this a compile time issue?

In the example below I would always check for not nil if the documentation said 
it may be nil so why can’t the compiler just make you do that anyways and 
provide the information right there in the declaration? I don’t understand 
where the runtime element of this is.

function GetThing: TThing; optional;

var
  thing: TThing;
begin
  thing := GetThing;
  if assigned(thing) then
writeln(thing.name);


> Invalid contracts are an error that should trigger during development, but 
> not necessarily when released. So coupling them with the default exception 
> mechanism is a valid solution.

Could you give a custom message for the exception or would it just say 
“Function X failed conditions”? Usually we give more detailed messages so we 
know went wrong. Since this is the compiler maybe it could say which condition 
failed, like “condition x < 0 failed”.

Regards,
Ryan Joseph

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

Re: [fpc-pascal] Optional param modifier

2019-04-14 Thread Sven Barth via fpc-pascal

Am 14.04.2019 um 16:05 schrieb Ryan Joseph:

On Apr 14, 2019, at 3:15 AM, Sven Barth via fpc-pascal 
 wrote:

Your idea requires exceptions as well. The compiler is not capable checking 
whether valid entries are passed in at compile time except for simple, constant 
cases, so runtime checks are needed and the only way to abort something is by 
exceptions.

My idea didn’t require the procedure to exit so I don’t see where an exception 
would be needed. It just says if a param was flagged you would need to check 
for nil before dereferencing other you get a compile time error.
As already said by Martin: the compiler *can not* determine all cases 
whether the parameter is Nil or not, so it *must* be done at runtime to 
ensure this. Otherwise the feature is just as useful as this:


=== code begin ===

{$macro on}
{$define optional:=}

procedure Blubb(aArg: TObject optional);
begin
end;

=== code end ===

I like the idea (because it feels Pascalish) to make a code section that checks 
requirements but the exit condition is up for debate. I personally wouldn’t use 
the feature if it meant I need to start the tedious process of wrapping 
everything in try blocks and taking on what performance costs there are to 
exceptions (we can’t opt into exceptions via modeswitch so I don’t know what 
those things are doing and where they are).
As Martin said: this is an error condition like an Assert that should 
trigger during development with the default result being a termination 
of the application.

We have custom error systems in our code also so forcing everyone into 
exceptions would not be nice. I could imagine a bail condition that was jumped 
to but it would have to be in the code section. That’s usually how we do it now 
anyways so it shouldn’t be too strange.

function MakeHero (name: string; hp: integer; level: integer): THero;
require
   name <> ‘’;
   hp > 0;
   (level > 0) and (level < 10);
begin
   …
bail
   MyCustomErrorHandler(‘MakeHero() params are invalid’);
   exit(THero.Invalid);
end;
Invalid contracts are an error that should trigger during development, 
but not necessarily when released. So coupling them with the default 
exception mechanism is a valid solution.


Regards,
Sven
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] mode switch madness

2019-04-14 Thread Sven Barth via fpc-pascal

Am 14.04.2019 um 17:03 schrieb Ryan Joseph:



On Apr 13, 2019, at 10:07 PM, Ben Grasset  wrote:

E.G, I sincerely doubt that anybody has *ever* thought, "man, I sure am glad that 
{$mode ObjFPC} does not allowed advanced records. It would be specifically bad if it 
did!" because it just doesn't matter if they weren't using advanced records to start 
with. It's just a lot of minor rules that nobody can really explain but that tend to add 
up in relatively annoying ways.


I like what Jonas did for the ObjC mode switch where he named them with 
versions. Maybe a {$mode objfpc2} one day.
My idea was to maybe add a mode ObjFPCExt or ObjFPCAdv which is quite a 
bit less conservative and might break backwards compatibility a bit more 
often when new features are added.


Regards,
Sven
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] mode switch madness

2019-04-14 Thread Sven Barth via fpc-pascal

Am 14.04.2019 um 04:07 schrieb Ben Grasset:
I dunno about setting them globally, but generally I do find 
modeswitches rather annoying, as the combination of features is pretty 
arbitrary, and they mostly just *disallow* things that couldn't break 
the code of people who weren't using those features to begin with if 
they were allowed.


E.G, I sincerely doubt that anybody has *ever* thought, "man, I sure 
am glad that {$mode ObjFPC} does not allowed advanced records. It 
would be specifically bad if it did!" because it just doesn't matter 
if they weren't using advanced records to start with. It's just a lot 
of minor rules that nobody can really explain but that tend to add up 
in relatively annoying ways.
The thing is that we do try to be backwards compatible and thus rather 
conservative with mode ObjFPC. E.g. the following code compiles without 
the modeswitch set, but not with:


=== code begin ===

program tmw;

{$mode objfpc}

type
  TTest = record
    private: LongInt;
    public: LongInt;
    protected: LongInt;
    strict: Longint;
  end;

begin

end.

=== code end ===

This hasn't always been done optimally in the past, e.g. when I added 
class helper support back in '12 or so I didn't protect the changes 
behind a modeswitch. Something I would not do today.


Also the modeswitch itself is definitely required as definitely not all 
language modes should support advanced records by default (e.g. TP or ISO).


Regards,
Sven
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] Optional param modifier

2019-04-14 Thread Martin Frb

On 14/04/2019 18:04, Martin Frb wrote:

On 14/04/2019 16:05, Ryan Joseph wrote:
On Apr 14, 2019, at 3:15 AM, Sven Barth via fpc-pascal 
 wrote:


Your idea requires exceptions as well. The compiler is not capable 
checking whether valid entries are passed in at compile time except 
for simple, constant cases, so runtime checks are needed and the 
only way to abort something is by exceptions.
My idea didn’t require the procedure to exit so I don’t see where an 
exception would be needed. It just says if a param was flagged you 
would need to check for nil before dereferencing other you get a 
compile time error.
First of all the max you should get is a note (warning, maybe). But 
never a compile time error.
As for your feature of getting a note from the compiler, if you deref a 
param (or other variable) that according to the compilers awareness 
could be nil at the time.


There is on need to say "optional".
Technically any nil-able var could be nil. So the compiler note should 
be for any such variable. Exactly like currently the "variable not 
initialized".


The downside: That would flood current code with compiler-notes. Because 
any param could be nil, even if the programmer has documented somewhere 
that this is not allowed.


But if pre-conditions where available, this could be combined.
The compiler could assume that if you wrote pre-conditions for a method, 
and that if you did non add "foo <> nil" to those conditions, then you 
expect that foo can be nil.
And in that case the compiler could add appropriate notes, if it finds 
you do not check for nil.


Existing code has no pre-conditions and is not affected. New code then 
must contain this.


Or the warning could apply to all code, but by default is not generated. 
You can enable it for each unit via commandline switch or directive. 
Again no "optional" needed.

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

Re: [fpc-pascal] Optional param modifier

2019-04-14 Thread Martin Frb

On 14/04/2019 16:05, Ryan Joseph wrote:

On Apr 14, 2019, at 3:15 AM, Sven Barth via fpc-pascal 
 wrote:

Your idea requires exceptions as well. The compiler is not capable checking 
whether valid entries are passed in at compile time except for simple, constant 
cases, so runtime checks are needed and the only way to abort something is by 
exceptions.

My idea didn’t require the procedure to exit so I don’t see where an exception 
would be needed. It just says if a param was flagged you would need to check 
for nil before dereferencing other you get a compile time error.
First of all the max you should get is a note (warning, maybe). But 
never a compile time error.


I have code like
  If a > 7 then
 (* If b = nil then *) b:= somedefault;
  foo();
  if a = 8 then
 a := b;  // compiler claim b is not initialized     (* a := b.Foo *)

So if your request for a compile time error was implemented, and above 
was a pointer deref on the last line, the code would not compile. Yet it 
is safe.


Also see my previous comment.
What is the point, if the compiler checks for potential issues, but only 
if I insert a request for the check on top of the potential unsave code.


If I have to write "optional" so the compiler checks for "if assigned" 
then what good is it? I can write "if assigned " immediately and save 
myself the optional.



And please do not counter this with: "But it documents for the user that 
he can use nil". The documentation is a separate distinct issue, and it 
can be solved in other ways.
You proposed one keyword to archive 2 features, be prepared to discuss 
each of them separately.



I like the idea (because it feels Pascalish) to make a code section that checks 
requirements but the exit condition is up for debate. I personally wouldn’t use 
the feature if it meant I need to start the tedious process of wrapping 
everything in try blocks and taking on what performance costs there are to 
exceptions (we can’t opt into exceptions via modeswitch so I don’t know what 
those things are doing and where they are).

There would be no need for try blocks.

It is the same as "assert". An assert raises an exception. But you do 
not write try except blocks for it.
An assert should never happen, therefore you do not handle it. An assert 
is a controlled crash of the app. Asserts are compiled into your app, if 
you test it. But you leave them out if you release.
Once you have tested (automatic test case), you no longer need the 
assert, because the case can never happen. (Or the third party using 
your code have to test, they follow the API. Or you allow nil for them, 
and you tested that it does work)


I understand that this is not the same you propose.
It is for cases where nil is NOT allowed, rather than for cases were nil 
is allowed. (as above, if nil is allowed, the code must be tested with 
nil. The compiler can never detect all cases, therefore the compiler can 
never enforce that you do "if assigned"... You may have done, without 
the compiler having noted)



We have custom error systems in our code also so forcing everyone into 
exceptions would not be nice. I could imagine a bail condition that was jumped 
to but it would have to be in the code section. That’s usually how we do it now 
anyways so it shouldn’t be too strange.

function MakeHero (name: string; hp: integer; level: integer): THero;
require
   name <> ‘’;
   hp > 0;
   (level > 0) and (level < 10);
begin
   …
bail
   MyCustomErrorHandler(‘MakeHero() params are invalid’);
   exit(THero.Invalid);
end;

You do not need the exit. Because the purpose of the assert is to abort 
the entire application (controlled crash).


If you get a call with invalid param, you have to assume this is because 
something else went wrong before. So in this case you have to assume 
worst case, something like the entire memory of the application has been 
corrupted.
There no longer is a way to rescue the app. All you can do is make sure 
that it will not do further damage. So you exit the app.


The IDE for example uses Application.OnException.
It tells the user that it is now unstable. Save your work and exit.

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

Re: [fpc-pascal] mode switch madness

2019-04-14 Thread Jonas Maebe

On 14/04/2019 17:03, Ryan Joseph wrote:




On Apr 13, 2019, at 10:07 PM, Ben Grasset  wrote:

E.G, I sincerely doubt that anybody has *ever* thought, "man, I sure am glad that 
{$mode ObjFPC} does not allowed advanced records. It would be specifically bad if it 
did!" because it just doesn't matter if they weren't using advanced records to start 
with. It's just a lot of minor rules that nobody can really explain but that tend to add 
up in relatively annoying ways.



I like what Jonas did for the ObjC mode switch where he named them with 
versions.


That was because Apple did the same with the Objective-C language: 
https://en.wikipedia.org/wiki/Objective-C#Objective-C_2.0 :)



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

Re: [fpc-pascal] mode switch madness

2019-04-14 Thread Ryan Joseph


> On Apr 13, 2019, at 10:07 PM, Ben Grasset  wrote:
> 
> E.G, I sincerely doubt that anybody has *ever* thought, "man, I sure am glad 
> that {$mode ObjFPC} does not allowed advanced records. It would be 
> specifically bad if it did!" because it just doesn't matter if they weren't 
> using advanced records to start with. It's just a lot of minor rules that 
> nobody can really explain but that tend to add up in relatively annoying ways.
> 

I like what Jonas did for the ObjC mode switch where he named them with 
versions. Maybe a {$mode objfpc2} one day.

Regards,
Ryan Joseph

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

Re: [fpc-pascal] Optional param modifier

2019-04-14 Thread Ryan Joseph

> On Apr 14, 2019, at 3:15 AM, Sven Barth via fpc-pascal 
>  wrote:
> 
> Your idea requires exceptions as well. The compiler is not capable checking 
> whether valid entries are passed in at compile time except for simple, 
> constant cases, so runtime checks are needed and the only way to abort 
> something is by exceptions.

My idea didn’t require the procedure to exit so I don’t see where an exception 
would be needed. It just says if a param was flagged you would need to check 
for nil before dereferencing other you get a compile time error.

I like the idea (because it feels Pascalish) to make a code section that checks 
requirements but the exit condition is up for debate. I personally wouldn’t use 
the feature if it meant I need to start the tedious process of wrapping 
everything in try blocks and taking on what performance costs there are to 
exceptions (we can’t opt into exceptions via modeswitch so I don’t know what 
those things are doing and where they are).

We have custom error systems in our code also so forcing everyone into 
exceptions would not be nice. I could imagine a bail condition that was jumped 
to but it would have to be in the code section. That’s usually how we do it now 
anyways so it shouldn’t be too strange.

function MakeHero (name: string; hp: integer; level: integer): THero;
require
  name <> ‘’;
  hp > 0;
  (level > 0) and (level < 10);
begin
  …
bail
  MyCustomErrorHandler(‘MakeHero() params are invalid’);
  exit(THero.Invalid);
end;



Regards,
Ryan Joseph

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

Re: [fpc-pascal] Can FPC optimize: if (s[i]='a') or ...

2019-04-14 Thread Bernd Oppolzer

Am 13.04.2019 um 21:55 schrieb Ralf Quint:

On 4/13/2019 12:30 PM, Alexey Tor. wrote:
E.g. i have a loop which test each s[i] char for several cases: 'a', 
'b', 'c'.


for i:= 1 to length(s) do

if (s[i]='a') or (s[i]='b') or (s[i]='c') then ...

Can FPC optimize it so it only reads s[i] once (to register), not 3 
times?



How about writing it in Pascal, something like

if s[i] in ['a'..'c'] then

or in case of no-sequential characters/values

if s[i] in ['a', 'b', 'c'] then...


Ralf



I'd like to second that ... the benefit that the optimizer may get
when IN is used ...

I would like to show you what my New Stanford Pascal compiler does;
it does not eliminate the common expressions s[i], but evaluates
them 3 times, given the original coding. But when the IN expression is used
(this coding: if s[i] in ['a', 'b', 'c'] then...)
it does a very good job. Because the three constants in the set are a
close range without holes in it, it checks in fact the range.

This is how it looks in IBM 370 ASSEMBLY language:

@@ 01AE:   SR    3,3      -- clear register 3
@@ 01B0:   IC    3,404(13,2)      -- insert character s[i] into 
register 3 (register 2 has index i, 404/13 is the address of s)
@@ 01B4:   AH    3,=H'-97'      -- subtract constant 'a' - should be 
EBCDIC 'a', but is ASCII 'a', because I tested on the PC :-)

@@ 01B8:   CL    3,=F'2'      -- check, if register 3 is between 0 and 2
@@ 01BC:   BC    2,L12      -- branch, if not

This is the result after the second step of the translation;
the first step is the translation to P-Code. The P-Code looks like this
(the Index I is on top of the stack at the beginning, the address of
S at the second position):

 01AE:   DEC  I,1  -- dec top of stack
 01AE:   IXA  1      -- use top of stack as index for 
address at second position
 01AE:   IND  C,0      -- replace top of stack (= address) 
with content of type char

 01AE:   ORD  -- convert to integer (does nothing)
 01B4:   LCA  S,C32'abc'  -- load character set constant
 01B4:   SLD  32,432  -- convert to binary set 
representation

 01B4:   INN  -- implement IN on elements on stack
 01BC:   FJP  L12  -- jump false

On the IBM mainframe, this P-Code is translated to what you see above.
On the other platforms (Windows, Linux, ...), the P-Code is interpreted -
a version of the compiler which generates native code on these platforms
has still to be done. But anyway: the language is fully portable, the 
results

are the same. (The P-Code is portable, the 370 implementation is of course
NOT portable - hence the problem when testing the 370 translation on the 
PC).


The optimization (implementing IN as a range check in this case) is
in fact done in stage 2, that is: in the P-Code to 370 translator.
The credits for this very fine compiler technology (which is about
40 years old) does not belong to me, but to many other people who
worked on this in the 1975 to 1990 era. I only did some extensions
to it in the last few years and ported the compiler to Windows and
Linux etc.

More information:

http://bernd-oppolzer.de/job9.htm
https://www.facebook.com/StanfordPascal

Kind regards

Bernd


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

Re: [fpc-pascal] mode switch madness

2019-04-14 Thread Anthony Walter
Someone said:

"You can do a {$i mysettings.inc}"

I give that a +1
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] Can FPC optimize: if (s[i]='a') or ...

2019-04-14 Thread Rainer Stratmann
On Samstag, 13. April 2019 22:30:55 CEST Alexey Tor. wrote:
> E.g. i have a loop which test each s[i] char for several cases: 'a',
> 'b', 'c'.
> 
> for i:= 1 to length(s) do
> 
> if (s[i]='a') or (s[i]='b') or (s[i]='c') then ...
> 
> Can FPC optimize it so it only reads s[i] once (to register), not 3 times?

You can optimise by yourself.

var
 c : char;
 l : longint;

begin
 l := length( s );
 for i := 1 to l do
  c := s[ i ];
  if ( c = 'a' ) or ( c = 'b' ) or ( c = 'c' ) then ...

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

Re: [fpc-pascal] mode switch madness

2019-04-14 Thread Florian Klämpfl
Am 14.04.2019 um 04:07 schrieb Ben Grasset:
> I dunno about setting them globally, but generally I do find modeswitches 
> rather annoying, as the combination of
> features is pretty arbitrary, and they mostly just *disallow* things that 
> couldn't break the code of people who weren't
> using those features to begin with if they were allowed.

It helps a lot to force a certain programming style.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] Optional param modifier

2019-04-14 Thread Sven Barth via fpc-pascal
Ryan Joseph  schrieb am So., 14. Apr. 2019,
00:17:

>
>
> > On Apr 13, 2019, at 6:01 PM, Sven Barth via fpc-pascal <
> fpc-pascal@lists.freepascal.org> wrote:
> >
> > Well, there is Oxygene's concept of Class Contracts (see
> > https://docs.elementscompiler.com/Concepts/ClassContracts/ ), so if
> > anything in that direction would be done I'd be inclined towards their
> > syntax (and I've played with the idea to implement this in FPC for quite
> > some time already).
>
> That’s an interesting idea. It’s certainly common that you test for these
> conditions at the top of the function and have bail out conditions so it
> makes sense to pull it out into syntax. But it has to rely on exceptions
> and all that overhead? That’s not so great if so.


Your idea requires exceptions as well. The compiler is not capable checking
whether valid entries are passed in at compile time except for simple,
constant cases, so runtime checks are needed and the only way to abort
something is by exceptions.

Regards,
Sven

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