Recent

Poll

I know the answer.

false
0 (0%)
unknown
3 (75%)
true
1 (25%)

Total Members Voted: 4

Author Topic: trinary logic with operator overloads  (Read 4767 times)

Kays

  • Full Member
  • ***
  • Posts: 116
  • Whasup!?
    • KaiBurghardt.de
trinary logic with operator overloads
« on: May 04, 2018, 02:22:02 pm »
Hi,

as an exercise I've attempted to implement a (small subset of some) trinary logic using operator overloads (since I barely use them, usually don't want to, but still require having some practice with such).

However the attached unit fails compiling saying
Code: [Select]
trinaryLogic.pas(12,41) Error: Impossible operator overload
trinaryLogic.pas(13,44) Error: Impossible operator overload
How come it's impossible? I've commented out those operator overloads and the overload for * “multiplication” does work, but those two don't? That's confusing.
Yours Sincerely
Kai Burghardt

Blaazen

  • Hero Member
  • *****
  • Posts: 2683
  • POKE 54296,15
    • Eye-Candy Controls
Re: trinary logic with operator overloads
« Reply #1 on: May 04, 2018, 03:31:46 pm »
I downloaded and tried but no idea. But do not use "true" and "false" it causes troubles. I changed to "_true" and "_false".
Lazarus 2.1.0 r59757M FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.11.2, Plasma 5.14.2
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

PascalDragon

  • Full Member
  • ***
  • Posts: 206
  • Compiler Developer
Re: trinary logic with operator overloads
« Reply #2 on: May 04, 2018, 03:43:40 pm »
Operator overloads are not allowed for operators that are already defined by the compiler. The "+" and "-" operators can be used on enum values during their declaration:
Code: Pascal  [Select]
  1. type
  2.   TTest = (
  3.     One,
  4.     Two,
  5.     Three,
  6.     Four = Three + Two,
  7.     Five = Four - One
  8.   );
And allowing operators in code, but disallowing them during declaration time looks a bit random...

Either use other operators or use a record type instead.

Kays

  • Full Member
  • ***
  • Posts: 116
  • Whasup!?
    • KaiBurghardt.de
Re: trinary logic with operator overloads
« Reply #3 on: May 04, 2018, 04:19:06 pm »
[…]
And allowing operators in code, but disallowing them during declaration time looks a bit random...
[…]
Huh, no; + and - are not overloaded for enumeration types but only in their declaration. Compiling
Code: Pascal  [Select]
  1. program foo(input, output, stderr);
  2.  
  3. type
  4.         test = (
  5.                 one,
  6.                 two,
  7.                 three,
  8.                 four = three + two,
  9.                 five = four - one
  10.         );
  11.  
  12. begin
  13.         writeLn(three + two);
  14. end.
fails due to
Code: [Select]
foo.pas(13,16) Error: Operation "+" not supported for types "test" and "test"So I don't think those operators are actually defined for enumerations in general. I can't find it documented in the reference guide. And it should not be, since AFAIK an enumeration type is not an integer type, though both are ordinals, but arithmetic operators are only defined for integers and reals.

PS: Mustn't it read colon equals four := three + two?
Yours Sincerely
Kai Burghardt

Thaddy

  • Hero Member
  • *****
  • Posts: 7228
Re: trinary logic with operator overloads
« Reply #4 on: May 04, 2018, 05:33:06 pm »
note the correct expression is ternary logic, not trinary logic. [edit] Oh I see that is allowed : https://en.wikipedia.org/wiki/Three-valued_logic but I never saw that terminology...in computer science papers]
Anyway in ternary logic you need to redefine true and false to ternary space. True and false are binary space by convention. And you did so already! But mixed things up a bit.
So, as suggested above, either redefine the naming or use a record or enumeration(with three members)  to return the result. Needs to be triplets because of three states.
Luckily such syntax is legal in FreePascal. Overloaded operants need not return just true or false..... which is quite a nice feature in this case.

As an aside it may be interesting to know that ternary compute in real life computing - as in calculator - (1840, Thomas Fowler) is actually older than today's binary compute systems. Of course Boolean logic itself is from 1847 and had at the time no mechanical or electronical implementation at all..

In your code the problem is just reduced to the use of true and false. Refine - or redefine - that and you're good to go.
« Last Edit: May 04, 2018, 05:57:44 pm by Thaddy »
inline variables like in D10.3 are a bit like Brexit: if you are given the wrong information it sounds like a good idea. Every kid loves candy, but it makes you fat and your teeth will disappear.

Kays

  • Full Member
  • ***
  • Posts: 116
  • Whasup!?
    • KaiBurghardt.de
Re: trinary logic with operator overloads
« Reply #5 on: May 04, 2018, 11:32:21 pm »
note the correct expression is ternary logic, not trinary logic. […]
Yeah, my primary language is German where „trinäre Logik“ sounds closer to „binäre Logik“. Just intuition.
[…] True and false are binary space by convention. And you did so already! But mixed things up a bit.

[…] Refine - or redefine - that and you're good to go.
I've made global substitutions for true and false yet still it doesn't compile. I wanted to make the implementation as easy/trivial as possible (typical for demonstration purposes). Using enumeration types has the “advantage” that succ/pred/ord are operable (out of the box).
Yours Sincerely
Kai Burghardt

ASerge

  • Hero Member
  • *****
  • Posts: 1004
Re: trinary logic with operator overloads
« Reply #6 on: May 05, 2018, 07:23:32 am »
I always thought operator overloading only works for structural types. Has that changed?

Thaddy

  • Hero Member
  • *****
  • Posts: 7228
Re: trinary logic with operator overloads
« Reply #7 on: May 05, 2018, 09:07:52 am »
I always thought operator overloading only works for structural types. Has that changed?
Well I just can't overload + and - for some reason, but all the others I can:
Code: Pascal  [Select]
  1. {$mode objfpc}{$H+}
  2. type
  3.   TMyEnum = (a,b,c);
  4.  
  5.   operator * (const a,b:TMyEnum)c:TMyEnum;
  6.   begin
  7.     c := TMyEnum(ord(a) * ord(b));
  8.   end;          
  9. var
  10.   aa:TMyEnum;
  11. begin
  12.   aa := b * c;
  13.   writeln(aa);
  14. end.
This form of operator overloading is already an old feature from 2.x. and {$mode objfpc} not {$mode delphi}
What you refer to are probably class operators for records, objects and classes.

In the above case there seems to be an issue for addition and substraction only and I think that is a bug, because the compiler only won't accept addition and substraction.
- On the one hand it says impossible operator overload for these two, hinting at a default implementation
- On the other hand it says enums.pas  Operation "-" not supported for types "TMyEnum" and "TMyEnum".
Fair enough, but all others can be overloaded: > >< = * div and or xor not in ** etc. Any thoughts this may warrant a bug report?

All this is despite Sven's explanation: seems a contradiction in terms, to some extend.
Anyway, ternary truth tables can be build from other operators.

« Last Edit: May 05, 2018, 09:41:13 am by Thaddy »
inline variables like in D10.3 are a bit like Brexit: if you are given the wrong information it sounds like a good idea. Every kid loves candy, but it makes you fat and your teeth will disappear.

Kays

  • Full Member
  • ***
  • Posts: 116
  • Whasup!?
    • KaiBurghardt.de
Re: trinary logic with operator overloads
« Reply #8 on: May 05, 2018, 12:41:40 pm »
Well I just can't overload + and - for some reason, but all the others I can:
That's what I reported.
[…] In the above case there seems to be an issue for addition and substraction only and I think that is a bug, because the compiler only won't accept addition and substraction.
- On the one hand it says impossible operator overload for these two, hinting at a default implementation
- On the other hand it says enums.pas  Operation "-" not supported for types "TMyEnum" and "TMyEnum".
[…] Any thoughts this may warrant a bug report? […]
(cheery) Yeah! Found another bug (fortunately in a non-critical situation).

I know, I can use any other operator, but - and + are quite common notation in electrical engineering, and …

OK, I've bluntly attempted overloading not, or and and. And apparently it works, despite not being documented in the diagram. That's where I looked in the first place, since – as I wrote in my first post – I need some practice in operator overloading.

The question remains why + and - are “impossible”. I couldn't find any relevant bug report with the terms “operator” and “enum”.
Yours Sincerely
Kai Burghardt

PascalDragon

  • Full Member
  • ***
  • Posts: 206
  • Compiler Developer
Re: trinary logic with operator overloads
« Reply #9 on: May 05, 2018, 02:41:11 pm »
[…]
And allowing operators in code, but disallowing them during declaration time looks a bit random...
[…]
Huh, no; + and - are not overloaded for enumeration types but only in their declaration.

Sorry, that should have read "And allowing operator overloads in code, but disallowing them during declaration time looks a bit random". If we'd allow allow overloads for + and - operators in code than users might ask for them in declarations as well which wouldn't work as there we have constant expressions.

PS: Mustn't it read colon equals four := three + two?
FPC itself supports both, though the Delphi compatible one is = (:= is even disallowed in Delphi modes).

OK, I've bluntly attempted overloading not, or and and. And apparently it works, despite not being documented in the diagram. That's where I looked in the first place, since – as I wrote in my first post – I need some practice in operator overloading.
Seems like they're indeed missing. Maybe you can issue a bug report towards the Documentation category?
Please note that and, or, not and xor exist in both logical and bitwise variations, the former returning Boolean the latter anything suitable.

The question remains why + and - are “impossible”. I couldn't find any relevant bug report with the terms “operator” and “enum”.
I've already explained to you why that is the case.

I always thought operator overloading only works for structural types. Has that changed?
FPC supports operator overloading for non-records for a long time already, though more restrictions had been placed on which operators overloads were possible. Since AFAIK 2.7.1 essentially all overloads are allowed that aren't already in use by the compiler itself. Please note that global operator overloads have the disadvantage that they can't be used inside a generic (at least not yet, I plan to experiment with that a bit).

Thaddy

  • Hero Member
  • *****
  • Posts: 7228
Re: trinary logic with operator overloads
« Reply #10 on: May 05, 2018, 05:59:43 pm »
Sven, I found a  bug that is lot more serious while playing with this. See Mantis 0033696.
demo code added for interested people:
Code: Pascal  [Select]
  1. {$mode objfpc}{$H+}
  2. type
  3.   ternary = (F, U, T);
  4.    
  5.   operator and (const a,b:ternary):ternary;inline;
  6.     const lookupAnd:array[ternary,ternary] of ternary =
  7.                     ((F,F,F),(F,U,U),(F,U,T));
  8.   begin
  9.     Result:= LookupAnd[a,b];
  10.   end;  
  11.          
  12.   operator or (const a,b:ternary):ternary;inline;
  13.     const lookupOr:array[ternary,ternary] of ternary =
  14.                    ((F,U,T),(U,U,T),(T,T,T));
  15.   begin
  16.     Result := LookUpOr[a,b];
  17.   end;          
  18. // compiler does not complain here too...., but....
  19.   operator not (const a:ternary):ternary;inline;
  20.     const LookupNot:array[ternary] of ternary =(T,U,F);
  21.   begin
  22.      Result:= LookUpNot[a];
  23.   end;          
  24.  
  25.  
  26. begin
  27.   // works as expected
  28.   writeln('AND');write(F and F);write(F and U);
  29.   writeln(F and T);write(U and F);write(U and U);
  30.   writeln(U and T);write(T and F);write(T and U);
  31.   writeln(T and T);
  32.   writeln;
  33.   //works as expected
  34.   writeln('OR');write(F or F);write(F or U);
  35.   writeln(F or T);write(U or F);write(U or U);
  36.   writeln(U or T);write(T or F);write(T or U);
  37.   writeln(T or T);
  38.   writeln;
  39.   // this fails, but compiles and runs w/o error indication.
  40.   // and renders the wrong results
  41.   writeln('NOT');
  42.   writeln(not F);// prints -1 instead of T, it does not pick the overload!
  43.   writeln(not U);// prints -2 instead of U, it does not pick the overload!
  44.   writeln(not T);// prints -3 instead of F, it does not pick the overload!
  45.   // which makes this next construct impossible while the compiler suggests it's legal.
  46.   {
  47.    writeln(T and not F);  
  48.   }
  49. end.
Either disallow it or it should be fixed.. This code compiles -Sewhn. Try to remove the comment and see the result from the last - perfectly valid - statement.
« Last Edit: May 05, 2018, 07:34:48 pm by Thaddy »
inline variables like in D10.3 are a bit like Brexit: if you are given the wrong information it sounds like a good idea. Every kid loves candy, but it makes you fat and your teeth will disappear.

Kays

  • Full Member
  • ***
  • Posts: 116
  • Whasup!?
    • KaiBurghardt.de
Re: trinary logic with operator overloads
« Reply #11 on: May 05, 2018, 08:12:45 pm »
Sven, […]
Who is Sven?
I found a  bug that is lot more serious while playing with this. […]
Great. Great, that I gave the impulse to play around with operator overloads and detect bugs. (x.x)
This code compiles […]
Uhm… Weird, my compiler version does not.  :(
Code: [Select]
Free Pascal Compiler version 3.0.4+dfsg-11 [2017/12/30] for x86_64
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling ohOh.pas
ohOh.pas(42,16) Error: Type mismatch
ohOh.pas(43,16) Error: Type mismatch
ohOh.pas(44,16) Error: Type mismatch
ohOh.pas(50) Fatal: There were 3 errors compiling module, stopping
Fatal: Compilation aborted
Error: /usr/bin/ppcx64 returned an error exitcode
Same with line 47 after uncommenting it.



[…]
The question remains why + and - are “impossible”. I couldn't find any relevant bug report with the terms “operator” and “enum”.
I've already explained to you why that is the case. […]
But why can't I add/subtract enumeration literals in a statement block? Only during the definition of the type?
« Last Edit: May 05, 2018, 08:24:00 pm by Kays »
Yours Sincerely
Kai Burghardt

Thaddy

  • Hero Member
  • *****
  • Posts: 7228
Re: trinary logic with operator overloads
« Reply #12 on: May 05, 2018, 09:17:48 pm »
Sven, […]
Who is Sven?
Alias PascalDragon and core developer. Deduction, Watson.
Quote
I found a  bug that is lot more serious while playing with this. […]
Great. Great, that I gave the impulse to play around with operator overloads and detect bugs. (x.x)
This code compiles […]
Uhm… Weird, my compiler version does not.  :(
Code: [Select]
Free Pascal Compiler version 3.0.4+dfsg-11 [2017/12/30] for x86_64
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling ohOh.pas
ohOh.pas(42,16) Error: Type mismatch
ohOh.pas(43,16) Error: Type mismatch
ohOh.pas(44,16) Error: Type mismatch
ohOh.pas(50) Fatal: There were 3 errors compiling module, stopping
Fatal: Compilation aborted
Error: /usr/bin/ppcx64 returned an error exitcode
Same with line 47 after uncommenting it.


Then it is a regression or you are using delphi mode. My code is accepted on all my platforms, except the last commented part with FPC trunk.
Quote
]
[…]
The question remains why + and - are “impossible”. I couldn't find any relevant bug report with the terms “operator” and “enum”.
I've already explained to you why that is the case. […]
But why can't I add/subtract enumeration literals in a statement block? Only during the definition of the type?
Sven explained that. But it is imho open for discussion.
« Last Edit: May 05, 2018, 09:19:52 pm by Thaddy »
inline variables like in D10.3 are a bit like Brexit: if you are given the wrong information it sounds like a good idea. Every kid loves candy, but it makes you fat and your teeth will disappear.

Thaddy

  • Hero Member
  • *****
  • Posts: 7228
Re: trinary logic with operator overloads
« Reply #13 on: May 06, 2018, 01:23:01 pm »
Note I use trunk, not 3.0.4., and there have been many compiler changes in trunk. In trunk, compiled with -Sew, my code throws no errors, runs, but takes the wrong codepath for the overloaded NOT operator, which makes the commented out and not fail. No errors, no warnings, no option  8-)
inline variables like in D10.3 are a bit like Brexit: if you are given the wrong information it sounds like a good idea. Every kid loves candy, but it makes you fat and your teeth will disappear.

Kays

  • Full Member
  • ***
  • Posts: 116
  • Whasup!?
    • KaiBurghardt.de
Re: trinary logic with operator overloads
« Reply #14 on: May 07, 2018, 10:48:13 pm »
But why can't I add/subtract enumeration literals in a statement block? Only during the definition of the type?
Sven explained that. But it is imho open for discussion.

Yeah, I've reviewed all posts by Sven:

Operator overloads are not allowed for operators that are already defined by the compiler. The "+" and "-" operators can be used on enum values during their declaration:[…]
[…] "And allowing operator overloads in code, but disallowing them during declaration time looks a bit random". If we'd allow allow overloads for + and - operators in code than users might ask for them in declarations as well which wouldn't work as there we have constant expressions. […]
I still don't understand. I try as hard as I can, but I simply can't.

Why doesn't the following work?
Code: Pascal  [Select]
  1. program op(input, output, stderr);
  2. type
  3.         enum = (zero, one, two, three = one + two);
  4. begin
  5.         writeLn(one + two); // ideally prints three
  6. end.
Yours Sincerely
Kai Burghardt