Re: [fpc-pascal] Tuples as variant arrays

2021-06-26 Thread Sven Barth via fpc-pascal

Am 26.06.2021 um 00:12 schrieb Ryan Joseph via fpc-pascal:

Is it possible something like this could work? Seems like it should but I get 
an error (got MyRecord expected variant).



{$mode objfpc}

program unit_name;

type
   TTuple = array of variant;

type
   MyRecord = record
   end;

var
   t: TTuple;
   r: MyRecord;
   i: variant;
begin
   t := [1,'string', r];
   for i in t do
 begin
   writeln(i);
 end;
end.


Variants by themselves can not handle records, because they can't carry 
type information. However by using TCustomVariantType one can come 
rather close though one still needs to some things manually:


=== code begin ===

program tvarrec;

{$mode objfpc}{$H+}
{$modeswitch advancedrecords}

uses
  Variants;

type
  generic TRecVariantType = class(TCustomVariantType)
  private type
    PT = ^T;
  public
    procedure Copy(var Dest: TVarData; const Source: TVarData;
  const Indirect: Boolean); override;
    procedure Clear(var V: TVarData); override;
    function ToVariant(const aArg: T): Variant;
    function FromVariant(const aArg: Variant): T;
  end;

{ TRecVariantType }

procedure TRecVariantType.Copy(var Dest: TVarData; const Source: TVarData;
  const Indirect: Boolean);
begin
  New(PT(Dest.vrecord));
  PT(Dest.vrecord)^ := PT(Source.vrecord)^;
end;

procedure TRecVariantType.Clear(var V: TVarData);
begin
  Dispose(PT(V.vrecord));
  V.vtype:=varEmpty;
  V.vrecord:=Nil;
end;

function TRecVariantType.ToVariant(const aArg: T): Variant;
begin
  TVarData(Result).vtype := VarType;
  New(PT(TVarData(Result).vrecord));
  PT(TVarData(Result).vrecord)^ := aArg;
end;

function TRecVariantType.FromVariant(const aArg: Variant): T;
begin
  if TVarData(aArg).VType <> VarType then
    EVariantTypeCastError.Create('Not a suitable record');
  Result := PT(TVarData(aArg).vrecord)^;
end;

type
  TMyRec = record
    f: LongInt;
    s: String;
    class operator := (const aOther: TMyRec): Variant;
    class operator := (const aOther: Variant): TMyRec;
  end;

  TMyRecVarType = specialize TRecVariantType;

var
  myrectype: TMyRecVarType;

{ TMyRec }

class operator TMyRec.:=(const aOther: TMyRec): Variant;
begin
  Result := myrectype.ToVariant(aOther);
end;

class operator TMyRec.:=(const aOther: Variant): TMyRec;
begin
  Result := myrectype.FromVariant(aOther);
end;

var
  v: Variant;
  varr: array of Variant;
  m, m2, m3: TMyRec;
  i: LongInt;
begin
  myrectype := TMyRecVarType.Create;
  try
    m.f := 42;
    m.s := 'Hello World';

    v := m;

    m2 := v;

    Writeln(m2.f, ' ', m2.s);

    varr := [1, 'Foobar', m];

    for i := Low(varr) to High(varr) do
  try
    m3 := varr[i];
    Writeln('Entry ', i, ': ', m3.f, ' ', m3.s);
  except
    Writeln('Entry ', i, ': failed to cast');
  end;
  finally
    myrectype.Free;
  end;
end.

=== code end ===

This code is merely a proof of concept and might be further improved.

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


Re: [fpc-pascal] Tuples as variant arrays

2021-06-26 Thread Michael Van Canneyt via fpc-pascal



On Fri, 25 Jun 2021, Dennis Lee Bieber via fpc-pascal wrote:


On Fri, 25 Jun 2021 16:12:41 -0600, Ryan Joseph via fpc-pascal
 declaimed
the following:


Is it possible something like this could work? Seems like it should but I get 
an error (got MyRecord expected variant).



{$mode objfpc}

program unit_name;

type
 TTuple = array of variant;

type
 MyRecord = record
 end;


Uhm, is there supposed to be some name designating storage space inside
that record declaration? Just my initial observation -- my Pascal
experience is Jensen via UCSD (college, on LSI-11) and Alcor (on
TRS-80 Model 4).


var
 t: TTuple;
 r: MyRecord;
 i: variant;
begin
 t := [1,'string', r];


https://wiki.freepascal.org/Variant
"""
Values of any simple data type can be stored in a variant variable.
"""
... would seem to reject the use of a record type (as records are,
themselves, made up of other "simple data types").


It is not possible to do this unless you create some custom variant manager
that can handle this. But even so, you'd need to make it a pointer to a
record, as a variant has limited, fixed size.

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