Or maybe I'm missing something in the implementation of this function, and it's still not an internal compiler function, as it's written in the description, or FPC somehow allows you to change the variable's type, which is totally insane to me?According to the link that you yourself indicated, it is written "If no type information was yet generated for the type, this statement will ensure that type information is available, i.e. the result is always non-nil".
Thank you very much. I had your option first, and it works and is very good, but it turns out that I think due to an implementation error, ALL integer types, regardless of their size in bytes, which is what I need, are the same for GetTypeKind...
And I don't think you're right about mandatory code generation for TypeOf.... TypeOf() generates, as you can see from the code and description, just the value of the constant, like "Роinter", like IsConstValue() of the constant type "boolean" Nothing else. And the compiler itself should, in theory, optimize them... But it always works only in the case of IsConstValue() and does not in the case of TypeOf(). I still don't know why I have to make a zoo of functions to decode a binary stream depending on the size of an integer argument in bytes instead of one universal function...
if TypeInfo(PtrUInt) = TypeInfo(Byte) then Writeln('BYTE')
This will evaluate to False at compile time. I'd need to check whether it is really safe to extend this further.
I would say that the safety of such an approach follows directly from the whole paradigm of the Pascal language with a pre-description of all types.... But the procedure below is not working yet because it generates unnecessary code...
procedure test41(a: ptrUint); inline; begin if TypeInfo(a) = TypeInfo(uint8) then Writeln('1') else if TypeInfo(a) = TypeInfo(uint16) then Writeln('2') else if TypeInfo(a) = TypeInfo(uint32) then Writeln('4') else if TypeInfo(a) = TypeInfo(uint64) then Writeln('8'); end;
ps: there is a hope in the near future to wait at least beta of new functionality, what with pleasure I will test in the real and working project? I don't think it will be very difficult because, at first glance, I just saw how TypeInfo is implemented in the source code of FPC, just there artificially limited functionality, as opposed to many other built-in compiler functions, which also return a constant.
pps: and on a side note, is there any way for "{$mode objfpc}" to use the simpler and more obvious "generics" syntax from the Delphi compatibility relim, just that I don't use?
[/quote]I would say that the safety of such an approach follows directly from the whole paradigm of the Pascal language with a pre-description of all types.... But the procedure below is not working yet because it generates unnecessary code...
“not working yet” and “generates unnecessary code” are two different points. The code will behave the same no matter if the compiler generates “unnecessary” code or not.
Do you actually have an example where it matters? Since the code you post will first typecast to ptruint, and only then get the typeinfo of ptruint.That's why I write that now it doesn't work and you have to do everything in other ways... But I want it to work like any other compiler function and to get dynamic branching within a procedure...
I would say that the safety of such an approach follows directly from the whole paradigm of the Pascal language with a pre-description of all types.... But the procedure below is not working yet because it generates unnecessary code...
“not working yet” and “generates unnecessary code” are two different points. The code will behave the same no matter if the compiler generates “unnecessary” code or not.
The problem is purely in the ultimate optimization. This is the code of an extremely complex and multiplatform telemetry data decoder, I optimized it to the limit, including assembler inserts where necessary, because it is called many millions of times in real time. So even a set of redundant and unoptimized constant comparison operations is, by measurements, up to minus 5% of performance. At the moment I have different procedures for all dimensions of integer arguments, for this reason, which is very confusing and complicated, but if everything will work as it should, they can be removed in one and universal, which code will be dynamically generated, depending on the type of application. Exactly the same thing I already did for the variant when the argument of the procedure is a constant. I used to have separate procedures for them too, but beautifully and stably working IsConstValue() helped me a lot. By the way, it would be very good to rewrite the Move procedure using it. So, I'm just for a large number of such procedures for the compiler itself, not for the language.
Right now I have something like:
procedure Decoder(a: uint64); inline; procedure Decoder(a: uint32); inline; procedure Decoder(a: uint16); inline; procedure Decoder(a: uint8); inline;
...and having to make a mandatory type change for variables with a sign. It's very annoying...
Something like this...
Or maybe I'm missing something in the implementation of this function, and it's still not an internal compiler function, as it's written in the description, or FPC somehow allows you to change the variable's type, which is totally insane to me?Use GetTypeKind:
procedure test40(a: PtrUint); inline; begin if GetTypeKind(a) = GetTypeKind(Byte) then Writeln('BYTE'); end;
program Test4;
uses typinfo,sysutils;
type aR = Record a,b : byte; end;
bR = Record b : byte; end;
var a : aR; b : bR; p : pointer;
procedure bytes(p : pointer; p0 : integer; nb : word); //Show nb bytes from p[p0] and write them in the console.
var i : word;
begin
for i:=0 to nb-1 do begin
if i mod 16 = 0 then write(IntToHex(sizeUInt(p+p0+i),8),' : ');
write(IntToHex(pbyte(p+p0+i)^,2),' ');
if i mod 16 = 15 then writeln else if i mod 4 = 3 then write('|');
if i mod 128 = 127 then writeln;
end;
writeln;
end;
BEGIN
p:=nil; with a do begin a:=0; b:=0; end; with b do b:=0; //Initialization of the variables (in case - maybe not really necessary here)
writeln('type(b)[-128] : '); bytes(PTypeInfo(TypeInfo(b)),-128,256); //Show 128 bytes before and from the begining of TTypeInfo struct bR.
// p:=PTypeInfo(TypeInfo(a));
END.
type(b)[-128] :
080B1050 : 28 1C 0C 08 |9C 40 0C 08 |24 48 0C 08 |00 00 00 00
080B1060 : 00 00 00 00 |00 00 00 00 |00 00 00 00 |00 00 00 00
080B1070 : 00 00 00 00 |00 00 00 00 |00 00 00 00 |00 00 00 00
080B1080 : 00 00 80 00 |00 00 00 00 |00 00 00 00 |00 00 00 00
080B1090 : 00 00 00 00 |00 00 00 00 |00 00 00 00 |00 00 00 00
080B10A0 : 00 00 00 00 |00 00 00 00 |00 00 00 00 |00 00 00 00
080B10B0 : 00 00 00 00 |0D 02 62 52 |00 00 00 00 |01 00 00 00
080B10C0 : 00 00 00 00 |00 00 00 00 |00 00 00 00 |B4 10 0B 08
080B10D0 : 0D 02 62 52 |B4 10 0B 08 |01 00 00 00 |01 00 00 00
080B10E0 : 2C 29 0B 08 |00 00 00 00 |D0 10 0B 08 |0E A4 04 08
080B10F0 : 3E A4 04 08 |26 A4 04 08 |26 A4 04 08 |3E A4 04 08
080B1100 : 3E A4 04 08 |3E A4 04 08 |14 A4 04 08 |3E A4 04 08
080B1110 : 26 A4 04 08 |1A A4 04 08 |32 A4 04 08 |1A A4 04 08
080B1120 : 3E A4 04 08 |38 A4 04 08 |32 A4 04 08 |3E A4 04 08
080B1130 : 3E A4 04 08 |38 A4 04 08 |38 A4 04 08 |20 A4 04 08
080B1140 : 08 A4 04 08 |08 A4 04 08 |3E A4 04 08 |3E A4 04 08
type(b)[-128] :
080A4080 : 00 00 00 00 |00 00 00 00 |00 00 00 00 |00 00 00 00
080A4090 : 00 00 00 00 |00 00 00 00 |00 00 00 00 |00 00 00 00
080A40A0 : 00 00 00 00 |0D 02 61 52 |00 00 00 00 |02 00 00 00
080A40B0 : 00 00 00 00 |00 00 00 00 |00 00 00 00 |A4 40 0A 08
080A40C0 : 0D 02 61 52 |A4 40 0A 08 |02 00 00 00 |02 00 00 00
080A40D0 : 5C 59 0A 08 |00 00 00 00 |5C 59 0A 08 |01 00 00 00
080A40E0 : C0 40 0A 08 |0D 02 62 52 |00 00 00 00 |01 00 00 00
080A40F0 : 00 00 00 00 |00 00 00 00 |00 00 00 00 |E4 40 0A 08
080A4100 : 0D 02 62 52 |E4 40 0A 08 |01 00 00 00 |01 00 00 00
080A4110 : 5C 59 0A 08 |00 00 00 00 |00 41 0A 08 |FE A3 04 08
080A4120 : 2E A4 04 08 |16 A4 04 08 |16 A4 04 08 |2E A4 04 08
080A4130 : 2E A4 04 08 |2E A4 04 08 |04 A4 04 08 |2E A4 04 08
080A4140 : 16 A4 04 08 |0A A4 04 08 |22 A4 04 08 |0A A4 04 08
080A4150 : 2E A4 04 08 |28 A4 04 08 |22 A4 04 08 |2E A4 04 08
080A4160 : 2E A4 04 08 |28 A4 04 08 |28 A4 04 08 |10 A4 04 08
080A4170 : F8 A3 04 08 |F8 A3 04 08 |2E A4 04 08 |2E A4 04 08
In any case, if this is indeed the case, it means that an indirect reading of the RTTI (or even worse, an indirect writing), as I've just done, is flawed. The direct use of the TypeInfo() (or more securely PTypeInfo(TypeInfo()) ) function is therefore - at the very least - recommended for each type structure.
Finally, something else after further tests: if you put all the records in a record and do a TypeInfo() only on it, the sub-records will also be 'updated' in memory recursively. (also to be confirmed)