They say Object Pascal is a classic, but every classic deserves
some modern love.

I've silently spent the last few months building something that
has actually been in the planning stages, on and off, for years.
I finally put head down to turn those notes into reality, and
while it's not quite ready for its full debut, I couldn't resist
sharing a "behind the scenes" look.

More soon. ;-)


----------------------
$ ../../pdr-cli/target/pdr DemoApp
PDR (Reference Implementation) v0.2.0
Copyright (c) 2025-2026 Graeme Geldenhuys

[INFO] Loading program: DemoApp
[INFO] OPDF version: 1
[INFO] Target architecture: x86_64
[INFO] Pointer size: 8 bytes
[INFO] Total records: 0
[INFO] Loaded 717 type(s), 8 variable(s), 4 function scope(s), and 34 line mapping(s)
[INFO] Program loaded successfully

[INFO] No arguments provided. Use "args" command to set them, then "run"

Type "help" for available commands

(pdr) run
[INFO] Running program: DemoApp
[INFO] Program started and paused at entry point
[INFO] You can now set breakpoints and use "continue" to start execution
(pdr) break DemoApp.pas:61
(pdr) continue
[INFO] Hit breakpoint at 0x00000000004012AE
(pdr) print ShortLabel
Shortlabel = 'PDR'
(pdr) print FullTitle
Fulltitle = 'OPDF version 1 ๐Ÿš€'
(pdr) print UniLabel
Unilabel = 'Unicode: Hello FPC ๐ŸŽ‰'
(pdr) print WorkWeek
Workweek = [Mon, Tue, Wed, Thu, Fri]
(pdr) inspect MyCircle
[INSPECT] MyCircle: TCircle (class, 8 bytes)
[INSPECT] parent chain: TCircle -> TObject
[INSPECT] fields (3):
  FName = 'Alpha'     [AnsiString(0), offset +16]
  FKind = skCircle (2)     [<enumeration type>, offset +24]
  FRadius = 3.14159     [Double, offset +32]
[INSPECT] properties (5):
  Name = 'Alpha'     [read FName]
  Kind = skCircle (2)     [read FKind]
  Radius = 3.14159     [read FRadius]
  Area = <method>     [read GetArea() - use 'call' to evaluate]
Perimeter = <method> [read GetPerimeter() - use 'call' to evaluate]
(pdr) print MyCircle.FRadius
MyCircle.FRadius = 3.14159
(pdr) inspect MyShape
[INSPECT] MyShape: IShape (interface)
[INSPECT] parent: IUnknown
[INSPECT] methods (3):
  Area = <method>
  Perimeter = <method>
  Description = <method>
(pdr) print Radii[2..4]
Radii[2] = 2.5
Radii[3] = 3.5
Radii[4] = 4.5
(pdr) locals
ACircle = TCircle(@$000074A0EC33A5F0) { FName: 'Alpha', FKind: skCircle (2), FRadius: 3.14159, Name: 'Alpha', Kind: skCircle (2), Radius: 3.14159 }
Info = 'Inspecting: Alpha'
Progress = 0
(pdr) callstack
[CALLSTACK]
#0 DebugSession at DemoApp.pas:65 (0x          4012B1)
#1 main at DemoApp.pas:110 (0x          40141E)
(pdr) set Counter = 99
[INFO] Counter set to 99
(pdr) print Counter
Counter = 99
(pdr) locals globals
Info = 'Inspecting: Alpha'
Progress = 0
Shortlabel = 'PDR'
Fulltitle = 'OPDF version 1 ๐Ÿš€'
Unilabel = 'Unicode: Hello FPC ๐ŸŽ‰'
Workweek = [Mon, Tue, Wed, Thu, Fri]
Radii = array[1..5] of Double = [1.5, 2.5, 3.5, 4.5, 5.5]
Mycircle = TCircle(@$00007C65AC7935F0) { FName: 'Alpha', FKind: skCircle (2), FRadius: 3.14159, Name: 'Alpha', Kind: skCircle (2), Radius: 3.14159 }
Counter = 99
(pdr) quit
Exiting...

----------------------
program DemoApp;
{$mode objfpc}{$H+}

{ PDR - Demonstrates: string types, enums, sets, class inspect, interface
  inspect, array slicing, locals listing, and live variable assignment. }

uses SysUtils;

type
  TShapeKind = (skRectangle, skTriangle, skCircle);
  TWeekday   = (Mon, Tue, Wed, Thu, Fri, Sat, Sun);

  {.//.$interfaces corba}
  IShape = interface(IUnknown)
    function Area: Double;
    function Perimeter: Double;
    function Description: AnsiString;
  end;
  {$interfaces com}

  TCircle = class
  private
    FName:   AnsiString;
    FKind:   TShapeKind;
    FRadius: Double;
    function GetArea: Double;
    function GetPerimeter: Double;
  public
    constructor Create(const AName: AnsiString; ARadius: Double);
    property Name:      AnsiString read FName;
    property Kind:      TShapeKind read FKind;
    property Radius:    Double     read FRadius;
    property Area:      Double     read GetArea;
    property Perimeter: Double     read GetPerimeter;
  end;

constructor TCircle.Create(const AName: AnsiString; ARadius: Double);
begin
  FName   := AName;
  FKind   := skCircle;
  FRadius := ARadius;
end;

function TCircle.GetArea: Double;
begin
  Result := Pi * FRadius * FRadius;
end;

function TCircle.GetPerimeter: Double;
begin
  Result := 2.0 * Pi * FRadius;
end;

procedure DebugSession(ACircle: TCircle);
var
  Info:     AnsiString;
  Progress: Integer;
begin
  Info     := 'Inspecting: ' + ACircle.Name;
  Progress := 0;
  Progress := Progress + 1;   { *** BREAKPOINT TARGET *** }
end;

var
  { String showcase: a longstanding pain point for FPC debugging }
  ShortLabel: ShortString;
  FullTitle:  AnsiString;
  UniLabel:   UnicodeString;

  { Set of named enum }
  WorkWeek: set of TWeekday;

  { Array for slice demo }
  Radii: array[1..5] of Double;

  { Class and interface }
  MyCircle: TCircle;
  MyShape:  IShape;   { nil รขย€ย” inspect still shows method signatures }

  { Counter for live variable-assignment demo }
  Counter: Integer;

const
  rocketUTF8 = #$F0#$9F#$9A#$80;
  tadaUTF16 = #$D83C#$DF89;

begin
  ShortLabel := 'PDR';
  FullTitle  := 'OPDF version 1 ' + rocketUTF8;
  UniLabel   := 'Unicode: Hello FPC ' + tadaUTF16;

  WorkWeek := [Mon, Tue, Wed, Thu, Fri];

  Radii[1] := 1.5;
  Radii[2] := 2.5;
  Radii[3] := 3.5;
  Radii[4] := 4.5;
  Radii[5] := 5.5;

  MyCircle := TCircle.Create('Alpha', 3.14159);
  MyShape  := nil;
  Counter  := 10;

  DebugSession(MyCircle);

  MyCircle.Free;
end.
_______________________________________________
fpc-devel maillist  -  [email protected]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply via email to