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