4

Good day,

TValue is a Delphi-2010 and up RTTI feature.

Following on from my earlier question, I had tried to make recurrent function to return a TValue as a n-dimensional. matrix(2D, 3D, 4D...)

for example, this procedure will show a n-dimensional matrix(it will list all elements from a n-dimensional matrix as TValue variable):

Procedure Show(X:TValue);
var i:integer;
begin
   if x.IsArray then
   begin
      for i:=0 to x.GetArrayLength-1 do
          show(x.GetArrayElement(i));
      writeln;
   end else
   write(x.ToString,' ');

end;

I don't understand how to create a function to create from a TValue an n-dimensional matrix. For example i need a Function CreateDynArray(Dimensions:array of integer; Kind:TTypeKind):TValue; and the function will return a TValue which is a dynamic array how contain the dimenssions for example:

Return=CreateDynArray([2,3],tkInteger); will return a TValue as tkDynArray and if i will show(Return) will list

0 0 0
0 0 0

Is not terminated. From a TValue i try to create a DynArray with n-dimensions

Procedure CreateArray(var Value:TValue; NewDimmension:integer; NewValue2Kind:TTypeKind; NewValue2:TValue; IsLast:Boolean);
var i:integer;
NewValue:TValue;
len:Longint;
begin
   If Value.IsArray then// we have components in this dimension
   begin
       for i:=0 to Value.GetArrayLength-1 do// list all
       begin
            NewValue:=Value.GetArrayElement[i];
            CreateArray(newValue,NewDimension,NewValue2Kind,NewValue2,IsLast);
            Value.SetArrayElement(i,NewValue);
       end;
   end;
end else
begin
      if isLast then
      begin
         len:=NewDimension;
         DynArraySetLength(PPointer(Value.GetRefereneToRawData)^,Value.TypeInfo,1,@len); //set length to NewDimension
         for i:=0 to NewDimension-1 do //Fill all with 0
           Value.SetArrayElement(i,NewValue2);
      end else
      begin
         len:=NewDimension;
         DynArraySetLength(PPointer(Value.GetRefereneToRawData)^,Value.TypeInfo,1,@len);//I will create len TValues
      end;
end;



var Index:array of integer;
    Value:TValue;
    ValuKind:TTypeKind;
......
......
....
Case token of
   tokInt:
   begin
        ValueKind:=tkInteger;
        Value:=0;   
   end;
 .....
 end;

 Index:=GetIndexFromSintacticTree;//for example if i have int[20][30] index=[20,30]
 for i:=0 to high(index) do
 begin
    if i = high(index) then CreateArray(Variable.Value,Index[i],ValueKind,Value,True)
    else CreateArray(Variable.Value,Index[i],ValueKind,Value,False)
    //Variable.Value is TValue
 end;
 //first TValue have 1 element, after that it will have 20 elements, and after that will have 20*30 elements

The ideea

Thank you very much, and have a nice day!

Community
  • 1
  • 1
user558126
  • 1,303
  • 3
  • 21
  • 42
  • What is TValue? What has RTTI have to do with it? Which version of Delphi do you have? – GolezTrol Dec 30 '10 at 13:52
  • 1
    There is a new version for Reflection since Delphi 2010, with this new RTTI theoretic you can do anything. – user558126 Dec 30 '10 at 13:59
  • It's quite hard to find the motivation to get into this question given that it is hard to see why anyone would want to do this. Is there some underlying motivation that goes beyond your personal distaste for Delphi generics? – David Heffernan Dec 30 '10 at 15:49
  • 1
    I had a software, it have about 15.000 lines code all with TValue, and arrays of TValue(it's like a scripting language). And it's hard to change now. And with generics you can't allocate dynamically new generics(not run time), and is a fatal problem. I have a question to you. Did you understood my task? – user558126 Dec 30 '10 at 15:58
  • The picture isn't getting any clearer. The question as to what TValue is remains unanswered. – David Heffernan Dec 30 '10 at 16:01
  • type T3DMatrix = array of array of array of Integer; Function TMyClass.GetMatrix:T3dMatrix; begin .... end; Value=ctx.GetType(TMyClass).GetMethod('GetMatrix').Invoke(TMyClass.Create, []); The return will be a 3D Matrix as TValue; I am tring to make a function which create TValue(create dyn arrays) how have n-dimensions with specific size. – user558126 Dec 30 '10 at 16:15
  • @user558126 I'm sure it all makes perfect sense to you!! – David Heffernan Dec 30 '10 at 17:52
  • 2
    @David, @Golez: TValue is a new type added in Delphi 2010. It's a record capable of representing any value in the Delphi type system. Sort of like a Variant, but different. What the OP wants is to find a way to make a TValue hold a dynamic array of arbitrary dimensions and base type, defined at runtime. As Barry points out, this is difficult because of the way dynamic arrays work. – Mason Wheeler Dec 31 '10 at 00:48

1 Answers1

5

To create a dynamic array dynamically, you need a reference to its type info structure (PTypeInfo) to pass to DynArraySetLength; calling DynArraySetLength and passing a reference to a nil pointer is how you can create a new dynamic array. If the specific shape of dynamic array does not already exist in your Delphi program, there will be no specific PTypeInfo pointer that the compiler will generate for you. In this case, you would have to generate the corresponding PTypeInfo data structure yourself. This is possible, though tedious.

Frankly, I'd recommend you use a different structure than built-in Delphi dynamic arrays to represent arrays in your scripting language-like problem. In the long run it will probably be a lot less work than trying to dynamically generate the low-level RTTI data, which is more likely to change from version to version now that it has a much higher level abstraction in the Rtti unit.

Barry Kelly
  • 41,404
  • 5
  • 117
  • 189
  • I really hope the format of TTypeInfo and TTypeData doesn't change, except to add new branches to the TTypeData union tree that fill in gaps in the existing RTTI. I've been doing a lot of theoretical work in the area of dynamic class and type generation in order to implement a scripting system that integrates seamlessly with compiled Delphi code through RTTI. I'm a week or two away from having a working POC compiler now, and it would be rather annoying to have to completely rework my type data generation code when a new version comes out. – Mason Wheeler Dec 31 '10 at 00:44
  • 1
    @Mason It's less a case of completely changing, than having more data appended on the end. It's a real PITA to jam in extra data without breaking code. As it is, the RTTI format contributes a fairly substantial size penalty largely because its encoding can't be optimized much. It would be nice to consider something like e.g. .NET metadata tables, which use a conciser representation. Instead, Delphi RTTI is left with every xref taking up a minimum of 4 bytes, and frequently with redundant strings for names that could be pooled. But that can't happen within the current framework. – Barry Kelly Dec 31 '10 at 01:35
  • Fair enough. It's a real mess trying to write code to read RTTI structures because of all of the inline data arrays without a static size, meaning the compiler can't find the field that comes next and you need a bunch of pointer math. If your new format could get rid of *that* I'd be all for it, and I'd only need to rewrite my generation code once. The part that bugged me was when you said "from version to version," implying that there will (might) be format revamps with each new release, or a significant fraction of them. That would be a pain. – Mason Wheeler Dec 31 '10 at 02:23