Recent

Author Topic: “case (a,b) of...” doesn’t compile  (Read 1635 times)

Weiss

  • Full Member
  • ***
  • Posts: 114
“case (a,b) of...” doesn’t compile
« on: September 25, 2023, 03:15:45 am »
I am trying pascal code of 30 years ago, written in vanila pascal. This statement doesn’t compile, and I honestly never seen this syntax before:

Code: Pascal  [Select][+][-]
  1.  
  2.  dataarraytype = RECORD
  3.                     CASE (r, c) OF
  4.                       r : (rp : ARRAY [dataindextype] OF real);
  5.                       c : (cp : ARRAY [cmpxindextype] OF complex)
  6.  
  7.  


compiler does not like “(“ , expects identifier. It is Fourier transform, I honestly can’t re-write this part without taking the code apart. I don’t understand the record altogether, if it is a record of two members, both arrays, why wasn’t it declared as such? I think case was needed, but don’t know why.

TRon

  • Hero Member
  • *****
  • Posts: 1847
Re: “case (a,b) of...” doesn’t compile
« Reply #1 on: September 25, 2023, 03:35:51 am »
see also: https://www.freepascal.org/docs-html/ref/refsu15.html

It is a variant record. Meaning that both rp and cp use overlapping memory. You can access both fields but both fields are of a different type (the variant).

you could probaly rewrite it as:
Code: Pascal  [Select][+][-]
  1. dataarraytype =
  2. record
  3.   case boolean of
  4.   true: (rp: array[dataindextype] of real;
  5.   false: (cp: array[cmpxindextype] of complex;
  6. end;
  7.  

440bx

  • Hero Member
  • *****
  • Posts: 3623
Re: “case (a,b) of...” doesn’t compile
« Reply #2 on: September 25, 2023, 04:45:43 am »
or even closer to what the OP showed...

Code: Pascal  [Select][+][-]
  1. type
  2.   TENUM = (r, c);
  3.  
  4. dataarraytype =
  5. record
  6.   case TENUM of
  7.   r : (rp : array[dataindextype] of real;
  8.   c : (cp : array[cmpxindextype] of complex;
  9. end;
  10.  
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 SP1 64bit.

TRon

  • Hero Member
  • *****
  • Posts: 1847
Re: “case (a,b) of...” doesn’t compile
« Reply #3 on: September 25, 2023, 05:51:01 am »
Even better 440bx. I missed the fact that it is probably an on-the-fly created enum type.

440bx

  • Hero Member
  • *****
  • Posts: 3623
Re: “case (a,b) of...” doesn’t compile
« Reply #4 on: September 25, 2023, 07:03:44 am »
...it is probably an on-the-fly created enum type.
That's my guess too based on how Pascal defines variants.
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 SP1 64bit.

Zvoni

  • Hero Member
  • *****
  • Posts: 2033
Re: “case (a,b) of...” doesn’t compile
« Reply #5 on: September 25, 2023, 09:06:30 am »
Aren't there some closing paranthesis' missing in 440bx sample?!?! Line 7+8
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

TRon

  • Hero Member
  • *****
  • Posts: 1847
Re: “case (a,b) of...” doesn’t compile
« Reply #6 on: September 25, 2023, 09:28:36 am »
@Zvoni:
Yes. Probably a simple typing (omission) error.

Warfley

  • Hero Member
  • *****
  • Posts: 1469
Re: “case (a,b) of...” doesn’t compile
« Reply #7 on: September 25, 2023, 10:39:45 am »
I would consider this to be a bug, because variant records should support anonymous type definitions, and this works perfectly well:
Code: Pascal  [Select][+][-]
  1.   TTest = record
  2.   case test: (A, B) of
  3.   A: (I: Integer);
  4.   B: (D: Double);
  5.   end;

But looking at the fpc source, the reading of the case is a bit wonky:
Code: Pascal  [Select][+][-]
  1.               fieldvs:=nil;
  2.               sorg:=orgpattern;
  3.               hs:=pattern;
  4.               searchsym(hs,srsym,srsymtable);
  5.               if not(assigned(srsym) and (srsym.typ in [typesym,unitsym])) then
  6.                 begin
  7.                   consume(_ID);
  8.                   consume(_COLON);
  9.                   fieldvs:=cfieldvarsym.create(sorg,vs_value,generrordef,[]);
  10.                   variantdesc^^.variantselector:=fieldvs;
  11.                   symtablestack.top.insertsym(fieldvs);
  12.                 end;
  13.               read_anon_type(casetype,true);
It is clearly intended to be able to read anonymous types (otherwise what is the read_anon_type call doing here), but it does not check if there is an Identifier before trying to read one.

The solution should be quite simple:
Code: Pascal  [Select][+][-]
  1.               fieldvs:=nil;
  2.               if token=_ID then
  3.                 begin
  4.                   sorg:=orgpattern;
  5.                   hs:=pattern;
  6.                   searchsym(hs,srsym,srsymtable);
  7.                   if not(assigned(srsym) and (srsym.typ in [typesym,unitsym])) then
  8.                     begin
  9.                       consume(_ID);
  10.                       consume(_COLON);
  11.                       fieldvs:=cfieldvarsym.create(sorg,vs_value,generrordef,[]);
  12.                       variantdesc^^.variantselector:=fieldvs;
  13.                       symtablestack.top.insertsym(fieldvs);
  14.                     end;
  15.                 end;
  16.               read_anon_type(casetype,true);
« Last Edit: September 25, 2023, 10:41:27 am by Warfley »

440bx

  • Hero Member
  • *****
  • Posts: 3623
Re: “case (a,b) of...” doesn’t compile
« Reply #8 on: September 25, 2023, 10:54:32 am »
Aren't there some closing paranthesis' missing in 440bx sample?!?! Line 7+8

and

@Zvoni:
Yes. Probably a simple typing (omission) error.

Yes, you are both right.  I copy/pasted TRon's code and modified it. I didn't notice the missing closing parentheses.  IOW, it's his fault (pointing that way ^ )
:D
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 SP1 64bit.

TRon

  • Hero Member
  • *****
  • Posts: 1847
Re: “case (a,b) of...” doesn’t compile
« Reply #9 on: September 25, 2023, 11:03:01 am »
IOW, it's his fault (pointing that way ^ )
Looks up, looking at birds flying over and whistles obliviously into the wind....  :-[

440bx

  • Hero Member
  • *****
  • Posts: 3623
Re: “case (a,b) of...” doesn’t compile
« Reply #10 on: September 25, 2023, 11:06:12 am »
@Warfley,

Something does not add up in allowing an identifier along with an anonymous enumeration to define a variant.

The problem is, the presence of an identifier name causes the record to have a field to store a value of that type but since the type is anonymous, it will quite likely be a problem when later the code has to reference the field to determine which variant applies.



IOW, it's his fault (pointing that way ^ )
Looks up, looking at birds flying over and whistles obliviously into the wind....  :-[
<chuckle>


FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 SP1 64bit.

Warfley

  • Hero Member
  • *****
  • Posts: 1469
Re: “case (a,b) of...” doesn’t compile
« Reply #11 on: September 25, 2023, 11:19:11 am »
@Warfley,

Something does not add up in allowing an identifier along with an anonymous enumeration to define a variant.

The problem is, the presence of an identifier name causes the record to have a field to store a value of that type but since the type is anonymous, it will quite likely be a problem when later the code has to reference the field to determine which variant applies.

Works perfectly fine:
Code: Pascal  [Select][+][-]
  1. type
  2.   TTest = record
  3.   case switch: (A, B) of
  4.   A: (I: Integer);
  5.   B: (D: Double);
  6.   end;
  7.  
  8. var
  9.   t: TTest;
  10. begin
  11.   t.switch:=A;
  12.   t.I:=42;
  13. end.

Problem is if you would have scoped enums
Code: Pascal  [Select][+][-]
  1. {$ScopedEnums On}
  2. type
  3.   TTest = record
  4.   case switch: (A, B) of
  5.   A: (I: Integer);
  6.   B: (D: Double);
  7.   end;
This doesn't compile anymore, because there is no scope from which to reference A or B, there you need
Code: Pascal  [Select][+][-]
  1. {$ScopedEnums On}
  2. type
  3.   TTestEnum = (A, B);
  4.   TTest = record
  5.   case switch: TTestEnum of
  6.   TTestEnum.A: (I: Integer);
  7.   TTestEnum.B: (D: Double);
  8.   end;

440bx

  • Hero Member
  • *****
  • Posts: 3623
Re: “case (a,b) of...” doesn’t compile
« Reply #12 on: September 25, 2023, 12:53:49 pm »
This doesn't compile anymore, because there is no scope from which to reference A or B, there you need
then you can no longer have the anonymous enumeration.  IOW, anonymous enumerations and scoped enumerations don't play nice with each other.

In addition to that, the anonymous enumeration cannot be used without an identifier which, if it is allowed, should also be allowed without the identifier but, if allowed, would leave no way to reference the enumeration constants outside the record's definition.

Allowing anonymous enumerations is problematic.



FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 SP1 64bit.

Weiss

  • Full Member
  • ***
  • Posts: 114
Re: “case (a,b) of...” doesn’t compile
« Reply #13 on: September 26, 2023, 12:26:59 am »
thank you all. I went with 440bx solution, declared enum and this part compiled well. Did not notice any missing parentheses haha.

In your further discussion, I also wonder why there is identifier preceding an enum? Does it need to be declared in declaration section? I thought anonymous kind does not have a name?

440bx

  • Hero Member
  • *****
  • Posts: 3623
Re: “case (a,b) of...” doesn’t compile
« Reply #14 on: September 26, 2023, 09:32:39 am »
I also wonder why there is identifier preceding an enum? Does it need to be declared in declaration section? I thought anonymous kind does not have a name?
The identifier preceding the enum defines a field that will be part of the record.  IOW, the identifier's presence defines a field that is meant to be used to determine which one of the variants applies.  The size of the record will be _larger_ if the identifier is present (since it defines a field.)

When there is no identifier then determining which variant applies rests on the programmer's shoulders.  Usually, an untagged variant is a way to typecast.  For instance, if one of the fields is a "ptruint" then the other field could be a "pointer" (plain or to something), since both a ptruint and a pointer are the same size, the presence of both fields in the variant is a way to typecast what is in that memory location.

HTH.
« Last Edit: September 26, 2023, 09:34:11 am by 440bx »
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 SP1 64bit.

 

TinyPortal © 2005-2018