Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I build an array of const?

Tags:

delphi

I am implementing an interpreter, and one of the functions my interpreter will support is like Delphi's Format. In fact, I'm implementing my function using SysUtils.Format. However, I'm having trouble building the second parameter to the function, the array of TVarRec.

Suppose I have the following code. For now, I just assume which Delphi variables the interpreted code will need access to (iVar1 and iVar2), but I still don't know how to put them into the structure that Format requires (arFormatArgs).

type TFormatArgs = array of TVarRec;

procedure RunInterpretedFormatFunction;
var
  iMyAge: integer;
  iMyIQ: integer;
  sCode: string;
  sText: string;
begin
  iMyAge := 5;
  iMyIQ := -5;
  sCode := 'Format(''My age is %d and my IQ is %d'', [iMyAge, iMyIQ])';
  sText := FormatThis(sCode, iMyAge, iMyIQ);
end;

function FormatThis(sFormatCode: string; iVar1: integer; iVar2: integer): string;
var
  sFormatString: string;
  arFormatArgs: TFormatArgs;
begin
  sFormatString := GetFormatString(sFormatCode); // I can implement this function
  arFormatArgs := ConstructFormatArgs(iVar1, iVar2); // NEED HELP HERE!
  result := SysUtils.Format(sFormatString, arFormatArgs);
end;

How can I implement my ConstructFormatArgs function in Delphi (not Assembly)?

like image 732
Sam Avatar asked Oct 23 '13 03:10

Sam


People also ask

How do you make an array const?

To create a const array in JavaScript we need to write const before the array name. The individual array elements can be reassigned but not the whole array.

Can you have a const array?

Arrays are Not Constants The keyword const is a little misleading. It does NOT define a constant array. It defines a constant reference to an array. Because of this, we can still change the elements of a constant array.

How do you declare a constant array in C++?

In C++, the most common way to define a constant array should certainly be to, erm, define a constant array: const int my_array[] = {5, 6, 7, 8};

Can you push to a const array?

Const Arrays For example, you can add another number to the numbers array by using the push method. Methods are actions you perform on the array or object. const numbers = [1,2,3]; numbers. push(4); console.


2 Answers

The array of const gives you the freedom to add strings, integers, floats and so on and having these formatted into a string. And there is no limit to how many items you can add.

The way Delphi deals with this issue is that the array of const really is a array of TVarRec's.

A TVarRec is a record of the following type:

TVarRec = record
  case Byte of
    vtInteger:    (VInteger: Integer; VType: Byte);
    vtBoolean:    (VBoolean: Boolean);
    vtChar:       (VChar: Char);
    vtExtended:   (VExtended: PExtended);
    vtString:     (VString: PShortString);
    vtPointer:    (VPointer: Pointer);
    vtPChar:      (VPChar: PChar);
    vtObject:     (VObject: TObject);
    vtClass:      (VClass: TClass);
    vtWideChar:   (VWideChar: WideChar);
    vtPWideChar:  (VPWideChar: PWideChar);
    vtAnsiString: (VAnsiString: Pointer);
    vtCurrency:   (VCurrency: PCurrency);
    vtVariant:    (VVariant: PVariant);

The type of the value inside the TVarRec is determined by the VType value.

This gives you the flexibility to add either type you wish to the array of const, like in the Format() function:

Format( '%s is a string, %d is an integer', ['string',10] );

Using the array of const in your own procedure is no big deal. Take a look at this example:

 procedure VarArraySample( AVarArray : array of const );
  var
    i : integer;
  begin
    for i := 0 to High(AVarArray) do
      do_something;
  end;

The function High() returns the last index of the array.

You can also convert the contents of the TVarRec. This example is taken from the Delphi on-line help and revamped a bit. The function converts a TVarRec to a string:

function VarRecToStr( AVarRec : TVarRec ) : string;
  const
    Bool : array[Boolean] of string = ('False', 'True');
  begin
    case AVarRec.VType of
      vtInteger:    Result := IntToStr(AVarRec.VInteger);
      vtBoolean:    Result := Bool[AVarRec.VBoolean];
      vtChar:       Result := AVarRec.VChar;
      vtExtended:   Result := FloatToStr(AVarRec.VExtended^);
      vtString:     Result := AVarRec.VString^;
      vtPChar:      Result := AVarRec.VPChar;
      vtObject:     Result := AVarRec.VObject.ClassName;
      vtClass:      Result := AVarRec.VClass.ClassName;
      vtAnsiString: Result := string(AVarRec.VAnsiString);
      vtCurrency:   Result := CurrToStr(AVarRec.VCurrency^);
      vtVariant:    Result := string(AVarRec.VVariant^);
    else
      result := '';
    end;
  end;

You can combine the two functions above to one function that converts all elements in the array of const into one string:

function VarArrayToStr( AVarArray : array of const ) : string;
  var
    i : integer;
  begin
    result := '';
    for i := 0 to High(AVarArray) do
      result := result + VarRecToStr( AVarArray[i] );
  end;

you will now be able to create your own Format() function. The Format() function scans for %'s and replaces the %something with the value in the array of const, depending on the format specifiers and precision specifiers.

like image 160
Glen Morse Avatar answered Oct 29 '22 03:10

Glen Morse


Found this code at https://groups.google.com/forum/#!topic/borland.public.delphi.objectpascal/-xb6O0qX2zc

procedure test(numArgs:integer; MyFormattingString:string);    
var
  v:array of tvarrec;
  i:integer;
begin
  setlength(v, numArgs);
  for i:=1 to numArgs do
  begin
    v[i-1].vtype:=vtpchar;
    v[i-1].vtpchar:=strnew(pchar(myDataSet.FieldByName(inttostr(i)).asstring));
  end;
  memo1.lines.add(Format(MyFormattingString,v);
  for i:=1 to numArgs do strdispose(v[i-1].vtpchar);
end;

Doesn't answer everything I have to deal with, but I think I know how to construct the array of TVarRec now.

like image 22
Sam Avatar answered Oct 29 '22 02:10

Sam