🚀 NitroPascal v0.4.0: Real-World Usage
TL;DR
NitroPascal v0.4.0 proves real-world viability with function pointers, structured RTL modules (Types, SysUtils, StrUtils, DateUtils), static library linking (raylib example included), performance benchmarks showing competitive results against Delphi, and a dramatically expanded C++ runtime. You can now build, benchmark, and ship production applications with confidence.
🎯 The Real-World Milestone
This release isn't about adding more features - it's about proving NitroPascal works in production. You can now:
✅ Use function pointers - Callbacks, event handlers, higher-order functions
✅ Link static libraries - Demonstrated with raylib game development library
✅ Structure with RTL modules - Types, SysUtils, StrUtils, DateUtils
✅ Benchmark performance - Comprehensive NitroPascal vs Delphi comparison
✅ Ship single executables - No DLL dependencies with static linking
✅ Build real apps - Complete toolkit for production software
🔥 What's New in v0.4.0
Function Pointers - Callbacks and Events
The big feature request is here. Function pointers (procedural types) enable callbacks, event-driven programming, and functional patterns:
type
TCompareFunc = function(const A, B: Integer): Integer;
TNotifyProc = procedure(const Msg: String);
procedure QuickSort(var A: array of Integer; Compare: TCompareFunc);
var
I, J, Pivot: Integer;
begin
if Length(A) <= 1 then Exit;
Pivot := A[Length(A) div 2];
I := 0;
J := High(A);
while I <= J do
begin
while Compare(A[I], Pivot) < 0 do Inc(I);
while Compare(A[J], Pivot) > 0 do Dec(J);
if I <= J then
begin
Swap(A[I], A[J]);
Inc(I);
Dec(J);
end;
end;
if J > 0 then QuickSort(Copy(A, 0, J + 1), Compare);
if I < High(A) then QuickSort(Copy(A, I, Length(A) - I), Compare);
end;
function Ascending(const A, B: Integer): Integer;
begin
Result := A - B;
end;
function Descending(const A, B: Integer): Integer;
begin
Result := B - A;
end;
var
Numbers: array of Integer;
begin
SetLength(Numbers, 5);
Numbers[0] := 5; Numbers[1] := 2; Numbers[2] := 8;
Numbers[3] := 1; Numbers[4] := 9;
// Sort ascending
QuickSort(Numbers, @Ascending);
// Sort descending
QuickSort(Numbers, @Descending);
end.
Use cases:
- Event handlers in GUI frameworks
- Callbacks in async operations
- Sorting with custom comparisons
- Plugin architectures
- Functional programming patterns
- Framework integration hooks
Static Library Linking - Ship Single Executables
Want to distribute a single .exe with no dependencies? Static linking is here, demonstrated with raylib:
program RaylibGame;
{$link raylib}
{$library_path './lib'}
// Raylib functions via static linking
procedure InitWindow(Width, Height: Integer; Title: PAnsiChar);
cdecl; external 'raylib.lib';
procedure CloseWindow(); cdecl; external 'raylib.lib';
function WindowShouldClose(): Boolean; cdecl; external 'raylib.lib';
procedure BeginDrawing(); cdecl; external 'raylib.lib';
procedure EndDrawing(); cdecl; external 'raylib.lib';
procedure ClearBackground(Color: Integer); cdecl; external 'raylib.lib';
procedure DrawText(Text: PAnsiChar; X, Y, Size, Color: Integer);
cdecl; external 'raylib.lib';
begin
InitWindow(800, 450, 'NitroPascal + Raylib!');
while not WindowShouldClose() do
begin
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText('Congrats! You created your first window!', 190, 200, 20, DARKGRAY);
EndDrawing();
end;
CloseWindow();
end.
This is a complete, working game window that compiles to a single executable with raylib statically linked. No DLLs to ship. Just one .exe file.
Benefits:
- Single-file deployment
- No DLL versioning issues
- Simplified distribution
- Faster load times
- Reduced attack surface
Structured RTL Modules - Professional Organization
The Runtime Library is now organized into standard Pascal modules for discoverability and maintainability:
Types - Base type declarations:
uses Types;
// Foundation types and utilities
SysUtils - System utilities and conversions:
uses SysUtils;
var
S: String;
I: Integer;
F: Double;
begin
// String conversions
S := IntToStr(42);
I := StrToInt('123');
F := StrToFloat('3.14');
// String manipulation
S := UpperCase('hello');
S := Trim(' spaces ');
S := StringReplace('test', 't', 'T', [rfReplaceAll]);
// File system
if FileExists('config.ini') then
ProcessConfig();
end.
StrUtils - Advanced string manipulation:
uses StrUtils;
var
S: String;
begin
S := StringOfChar('*', 40); // '****************************************'
S := LeftStr('Hello', 3); // 'Hel'
S := RightStr('World', 3); // 'rld'
end.
DateUtils - Date/time functions (foundation):
uses DateUtils;
// Date/time operations (initial implementation)
This modular organization makes the API discoverable, maintainable, and familiar to Delphi developers.
Performance Benchmarks - Competitive Results
The included benchmark suite provides quantitative comparison between NitroPascal and Delphi:
Test scenarios:
- String operations (concatenation, manipulation, conversions)
- Array operations (creation, access, iteration)
- Mathematical computations (loops, calculations)
Results show NitroPascal delivers competitive performance thanks to:
- LLVM optimization pipeline
- Efficient C++ code generation
- Optimized RTL implementation
- Native compilation via Zig
Run the benchmarks yourself (bin
folder):
NPBench_Delphi.exe (compiled in Delphi)
NPBench.exe (compiled in NitroPascal)
Enhanced String Library - Complete Unicode Support
New string functions for advanced manipulation and wide character support:
var
S: String;
Ch: Char;
Buffer: array[0..255] of WideChar;
begin
// Create repeated character strings
S := StringOfChar('=', 80); // '===============....'
// Character case conversion
Ch := UpCase('a'); // 'A'
// Numeric to string (legacy format)
Str(42:4, S); // ' 42' (width 4)
Str(3.14:6:2, S); // ' 3.14' (width 6, precision 2)
// Wide character operations
WideCharToString(Buffer);
StringToWideChar(S, Buffer, 256);
// Direct buffer to string conversion
SetString(S, @Buffer[0], WideCharLen(Buffer));
end.
Expanded Math Library - Scientific Computing
Complete mathematical toolkit for scientific and engineering applications:
var
X, Y, Result: Double;
begin
// Logarithms
Result := Ln(2.718); // Natural log
Result := Log10(100); // Base-10 log (2.0)
Result := Log2(8); // Base-2 log (3.0)
Result := LogN(3, 27); // Custom base log (3.0)
// Exponential and power
Result := Exp(1.0); // e^1 ≈ 2.718
Result := Power(2, 10); // 2^10 = 1024
// Integer and fractional parts
Result := Int(3.7); // 3.0
Result := Frac(3.7); // 0.7
// Hyperbolic functions
Result := Sinh(1.0); // Hyperbolic sine
Result := Cosh(1.0); // Hyperbolic cosine
Result := Tanh(1.0); // Hyperbolic tangent
Result := ArcSinh(0.5); // Inverse hyperbolic sine
Result := ArcCosh(1.5); // Inverse hyperbolic cosine
Result := ArcTanh(0.5); // Inverse hyperbolic tangent
// Angle calculations
Result := ArcTan2(1.0, 1.0); // Proper quadrant-aware arctangent
// Mathematical constants
Result := Pi; // 3.14159265358979323846...
end.
Enhanced File I/O - Complete Delphi Compatibility
New file operations for complete Delphi text file compatibility:
var
F: TextFile;
Ch: Char;
Line: String;
ErrorCode: Integer;
begin
Assign(F, 'data.txt');
Reset(F);
try
// Character-by-character reading
while not Eof(F) do
begin
Read(F, Ch);
if Eoln(F) then
WriteLn('End of line reached');
end;
// Skip whitespace and test for end
Reset(F);
SeekEof(F); // Skip whitespace, check EOF
SeekEoln(F); // Skip whitespace, check EOL
// Force write
Flush(F);
// Truncate at current position
Truncate(F);
Close(F);
// File operations on closed file
Erase(F); // Delete file
Rename(F, 'newname.txt'); // Rename file
// Check I/O errors
ErrorCode := IOResult;
if ErrorCode <> 0 then
WriteLn('I/O Error: ', ErrorCode);
except
Close(F);
end;
end.
Enhanced Memory Functions - Efficient Operations
Type-specific fill operations for better performance:
var
ByteArray: array[0..99] of Byte;
WordArray: array[0..99] of Word;
DWordArray: array[0..99] of Cardinal;
P: Pointer;
begin
// Zero-filled allocation
P := AllocMem(1024); // Allocate and zero-fill
try
// Work with memory
finally
FreeMem(P);
end;
// Type-specific fills (more efficient than FillChar)
FillByte(ByteArray, Length(ByteArray), $FF);
FillWord(WordArray, Length(WordArray), $FFFF);
FillDWord(DWordArray, Length(DWordArray), $FFFFFFFF);
end.
Code Generation Improvements - Better Debugging
Source position tracking in generated C++ code:
// Original Pascal code at line 42
WriteLn('Hello');
Generates:
#line 42 "myprogram.pas"
np::WriteLn(u"Hello");
Benefits:
- Error messages reference original Pascal source lines
- Debugger shows Pascal source positions
- Stack traces map to Pascal code
- Better development experience
💪 Why This Matters
v0.3.0 asked: "Is NitroPascal production-ready?"
v0.4.0 answers: "Yes, and here's proof!"
This release provides quantifiable evidence of real-world viability:
- 📊 Benchmarks - Measured performance comparison against Delphi
- 🎮 Raylib integration - Real library, static linked, single executable
- 🗂️ Structured RTL - Professional organization for production use
- 🔧 Function pointers - Essential pattern for frameworks and callbacks
- 🚀 Complete toolkit - Everything needed for production applications
🎁 The Growing RTL
The Runtime Library continues expanding with professional organization:
Organized Modules:
- Types - Base type declarations
- SysUtils - System utilities
- StrUtils - String utilities
- DateUtils - Date/time functions (initial)
Key Features:
- np::String - Complete Unicode string support
- np::DynArray - Dynamic arrays
- np::Set - Set operations
- File I/O wrappers - Full Delphi compatibility
- Exception support - Robust error handling
- Math functions - Scientific computing
- Memory management - Efficient operations
Everything maintains true Delphi semantics while generating optimal C++ code that compiles to native machine code via Zig's LLVM backend.
📚 Documentation
Complete feature tracking:
- COVERAGE.md - Complete feature checklist (✓ implemented vs planned)
- DESIGN.md - Architecture deep dive
- MANUAL.md - User guide and reference
Check the docs to see exactly what you can build today!
🚀 Getting Started
# Clone the repository
git clone https://github.com/tinyBigGAMES/NitroPascal
cd NitroPascal
# Build the raylib example
cd bin\projects\raylib\core_basic_window
nitro build
nitro run
# Run the benchmark suite
cd bin\projects\NPBench
nitro build
nitro run
# Create your own project
cd bin\projects
nitro init myproject -t program
cd myproject
nitro build
nitro run
Example: Function pointer callback pattern:
program CallbackDemo;
type
TProcessCallback = procedure(const Item: String);
procedure ProcessList(Items: array of String; Callback: TProcessCallback);
var
I: Integer;
begin
for I := 0 to High(Items) do
Callback(Items[I]);
end;
procedure PrintItem(const Item: String);
begin
WriteLn('Processing: ', Item);
end;
procedure CountItem(const Item: String);
begin
Inc(GlobalCount);
WriteLn('Item #', GlobalCount, ': ', Item);
end;
var
Files: array of String;
GlobalCount: Integer;
begin
SetLength(Files, 3);
Files[0] := 'file1.txt';
Files[1] := 'file2.txt';
Files[2] := 'file3.txt';
GlobalCount := 0;
WriteLn('Using PrintItem callback:');
ProcessList(Files, @PrintItem);
WriteLn('Using CountItem callback:');
ProcessList(Files, @CountItem);
end.
This is production-ready callback handling. Framework integration. Event systems. Plugin architectures. All possible now.
🌐 Community
- GitHub: tinyBigGAMES/NitroPascal
- Discord: Join our community
- Issues: Found a bug? Report it
- Discussions: Share your projects in discussions
🔮 What's Next?
With function pointers, static linking, structured RTL, and proven performance, NitroPascal has the foundation for any application type. What do YOU want to build? Let us know in discussions!
🎊 The Bottom Line
NitroPascal v0.4.0 proves real-world viability.
Function pointers enable callbacks and frameworks. Static linking ships single executables. Structured RTL provides professional organization. Benchmarks show competitive performance. The raylib example demonstrates real library integration.
Build games. Build utilities. Build applications.
Write pure Delphi. Link static libraries. Get native performance. Ship everywhere. 🚀
File Integrity
Files are signed with minisign using this public key:
RWTqBYfsUOCQscb6ZeknLC0On3cvWCVzMzlHamtgXNaDOO4bNs3WCSkV