Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SimpleXML: Union information missing in output #177

Open
andre2007 opened this issue Jan 26, 2023 · 6 comments
Open

SimpleXML: Union information missing in output #177

andre2007 opened this issue Jan 26, 2023 · 6 comments

Comments

@andre2007
Copy link
Contributor

For this Delphi unit

unit Unit3;

interface

uses System.Types;

type TMyRect = record
  private
  public
  case Integer of
    0: (Left, Top, Right, Bottom: FixedInt);
    1: (TopLeft, BottomRight: TPoint);
  end;

implementation

end.

The SimpleXML output looks like this:

<unit name="Unit3.pas">
  <uses name="System.Types"/>
  <structure name="TMyRect" name_with_generic="TMyRect" type="record">
    <variable name="Left" declaration="Left: FixedInt">
    </variable>
    <variable name="Top" declaration="Top: FixedInt">
    </variable>
    <variable name="Right" declaration="Right: FixedInt">
    </variable>
    <variable name="Bottom" declaration="Bottom: FixedInt">
    </variable>
    <variable name="TopLeft" declaration="TopLeft: TPoint">
    </variable>
    <variable name="BottomRight" declaration="BottomRight: TPoint">
    </variable>
  </structure>
</unit>

From the output I cannot see that the Delphi source code defines here an union. Therefore the variables Left,Top,Right,Bottom shares the same memory like TopLeft,BottomRight. This information I need to write wrapper code based on the SimpleXML output. Could you check whether you could add this information?

@michaliskambi
Copy link
Collaborator

Terminology note:

Below I will try to stick to Delphi / FPC terminology, "record with variant part, that has many variants".

So I looked at code processing it (TParser.ParseRecordCase).

  1. PasDoc tracks whether we're inside a "variant part" through IsInRecordCase variable passed around.

    So we could easily add a simple boolean to fields like in_record_variant="true". This would mean that in the above example, all 6 fields (Left, Top, Right, Bottom, TopLeft, BottomRight) just get in_record_variant="true" in SimpleXML output.

  2. PasDoc does not track, currently, when does one variant (like Left, Top, Right, Bottom: FixedInt) stop and another one (like TopLeft, BottomRight: TPoint) begin. Just as you see in the output, PasDoc parser just adds all 6 fields to the record, forgetting about the whole "record with variants" stuff.

    We could improve it of course, to store information about record variants. I guess the most natural representation would expose the variants as nested XML elements, so the end would look like this:

    <unit name="Unit3.pas">
      <uses name="System.Types"/>
      <structure name="TMyRect" name_with_generic="TMyRect" type="record">
        <variant_part type="Integer">
          <variant value="0">
            <variable name="Left" declaration="Left: FixedInt">
            </variable>
            <variable name="Top" declaration="Top: FixedInt">
            </variable>
            <variable name="Right" declaration="Right: FixedInt">
            </variable>
            <variable name="Bottom" declaration="Bottom: FixedInt">
            </variable>
          </variant>
          <variant value="1">
            <variable name="TopLeft" declaration="TopLeft: TPoint">
            </variable>
            <variable name="BottomRight" declaration="BottomRight: TPoint">
            </variable>
          </variant>
        </variant_part>
      </structure>
    </unit>

I see you use PasDoc XML output for an interesting application, Embarcadero/DelphiFMX4Python#42 :) Which option do you need -

AD 1 (simple in_record_variant boolean information per-field)

or AD 2 (full information about record variants, how are fields divided between them)?

@andre2007
Copy link
Contributor Author

For generating code like in my scenario the full information is needed. Therefore if the info could be added, how the fields are divided, this would be really great.

@michaliskambi
Copy link
Collaborator

Noted. I will try to do it around this weekend. If I fail, and this gets critical for your usage, please feel free to ping me :)

@andre2007
Copy link
Contributor Author

Thanks a lot. This part is not urgent. If it is solved in some weeks it is fine :)

@michaliskambi
Copy link
Collaborator

Note: I let this task hang for a long time, but it's still on my TODO list -- it is clear how to do it, I just need to find time.

I'll be busy for 2 weeks now preparing for a conference talk, but after that I hope to handle this task, and also make new PasDoc release, in July this year.

If this task is more urgent, please ping me :)

@andre2007 In somewhat related news, I noticed you work on exposing Pascal OOP libraries in other languages, in particular D. I am researching about making Castle Game Engine available from other languages too, looking first at Python, but likely at other modern languages (like D or Rust) too. If this (exposing Castle Game Engine to other languages, like D or Rust or Python) is something you'd be interested in helping with, please let me know (here, or by email to michalis@castle-engine.io).

@andre2007
Copy link
Contributor Author

Yes, the idea is to have a generic tool which generates just based on SimpleXML files a Delphi library project and the D wrapper source code files to access the library file. The approach heavily using Delphi RTTI which is exposed as functions in the Delphi library (DLL on Windows). The approach is working fine, but so far I created every part manually.

I started a generator which should create all parts automatically but hit a dead end. My design was bad and I need to restart with a better design. I already have a better design in my mind which will solve various problems (including generating wrapper code not just for the language D but others too). But time is also my biggest issue.

I started with wrapping Firemonkey / Delphi RTL. When this is working I will also try Castle Game Engine. It will be interesting to see how the performance of the game engine is affected by calling it through a wrapper.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants