Re: [fpc-pascal] Can FPC optimize: if (s[i]='a') or ...
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 ...
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
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 ...
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
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
> 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
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
> 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
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
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
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
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
> 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
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
> 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
> 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
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
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
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
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
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
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
> 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
> 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 ...
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
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 ...
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
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
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