Skip to content

Releases: tinyBigGAMES/JetPascal

🚀 JetPascal v0.2.0: Breaking Down the Wall

18 Nov 20:24

Choose a tag to compare

TL;DR

JetPascal v0.2.0 is the Pascal-to-C++ transpiler that breaks down the traditional barrier between Pascal and the C++ ecosystem. Mix Pascal and C++ freely, include headers directly, link libraries with a single directive, and access 40+ years of C++ libraries without writing wrapper code. Complete Pascal language support, built-in unit testing, cross-platform compilation, and a revolutionary smart token architecture.

🎯 The Game-Changing Feature

Zero-Friction C++ Ecosystem Access

For decades, Pascal developers faced a critical barrier: accessing C++ libraries required DLL wrappers, FFI bindings, and constant maintenance overhead. JetPascal eliminates this completely.

Unknown tokens = C++ - Don't recognize it? Emit it as C++
Direct header inclusion - #include_header '<vector>' brings C++ into scope
Unrestricted C++ blocks - #startcpp/#endcpp for ANY C++ code
Static library linking - #link 'raylib' - done
Seamless token mixing - Pascal and C++ in the same expression
No wrappers needed - Zero FFI overhead, zero binding maintenance

🔥 What's New in v0.2.0

The "Living in C++" Philosophy

JetPascal operates at the C++ boundary at all times:

  1. Pascal as Syntactic Sugar - Pascal transpiles to C++23
  2. Transparent Fallthrough - Unknown tokens emit as raw C++
  3. C++ Semantics - Leverage C++23 features for Pascal behavior
  4. Zero Overhead - No FFI, no marshaling, direct code generation

Example - Mixing Pascal and C++:

program MixedDemo;

#include_header '<cmath>'

var
  LValue: Integer;
  LResult: Double;

begin
  // Pure Pascal
  LValue := 10;
  WriteLn('Pascal: Value = ', LValue);
  
  // Pure C++ - std::cout is not a Pascal token, emitted as C++!
  std::cout << "C++: Hello!" << std::endl;
  
  // Mixed: Pascal WriteLn with C++ expression
  WriteLn('Square root: ', std::sqrt(16.0));
  
  // Mixed: C++ expression in Pascal assignment
  LResult := std::pow(2.0, 8.0);
  WriteLn('2^8 = ', LResult);
end.

This just works. No wrappers. No bindings. Pascal calls C++, C++ calls Pascal - seamlessly.

Unrestricted C++ Blocks - Complete Freedom

Need to write complex C++ code? Use #startcpp/#endcpp:

program AdvancedCpp;

#include_header '<vector>'
#include_header '<algorithm>'

var
  LSum: Integer;

begin
  LSum := 0;
  
  #startcpp
  // ANY C++ code - ZERO restrictions!
  std::vector<int> numbers = {5, 2, 8, 1, 9};
  
  // Sort with C++ STL
  std::sort(numbers.begin(), numbers.end());
  
  // Lambda expressions
  auto multiply = [](int a, int b) { return a * b; };
  std::cout << "10 * 5 = " << multiply(10, 5) << std::endl;
  
  // Calculate sum for Pascal variable
  for (const auto& n : numbers) {
    LSum += n;  // Modifying Pascal variable from C++!
  }
  
  // Range-based for
  std::cout << "Sorted: ";
  for (const auto& n : numbers) {
    std::cout << n << " ";
  }
  std::cout << std::endl;
  #endcpp
  
  WriteLn('Sum from C++: ', LSum);  // Using the value C++ calculated
end.

C++ lambdas. STL algorithms. Range-based loops. Templates. All available.

Static Library Linking - Single Executable Deployment

The raylib example that changes everything:

program RaylibGame;

#optimization releasesmall
#include_header '"raylib.h"'

#link 'raylib'
#link 'gdi32'
#link 'opengl32'
#link 'winmm'

begin
  InitWindow(800, 450, "JetPascal + raylib!");
  SetTargetFPS(60);
  
  while not WindowShouldClose() do
  begin
    BeginDrawing();
      ClearBackground(RAYWHITE);
      DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY);
    EndDrawing();
  end;
  
  CloseWindow();
end.

This is a complete, working game window that compiles to a single .exe with raylib statically linked!

  • ✅ No wrapper code
  • ✅ No DLL dependencies
  • ✅ Direct C++ function calls
  • ✅ Single-file deployment
  • ✅ Production-ready

Complete Pascal Language Support

All the Pascal features you expect:

Basic Types

var
  LInt: Integer;      // 32-bit signed
  LInt64: Int64;      // 64-bit signed
  LUInt: UInt64;      // 64-bit unsigned
  LCard: Cardinal;    // 32-bit unsigned
  LWord: Word;        // 16-bit unsigned
  LByte: Byte;        // 8-bit unsigned
  LBool: Boolean;     // Boolean
  LChar: Char;        // Character
  LSingle: Single;    // 32-bit float
  LDouble: Double;    // 64-bit float
  LStr: String;       // Unicode string

Pointers and Memory

var
  LPtr: PInteger;
  LValue: Integer;

begin
  // Allocate
  New(LPtr);
  LPtr^ := 42;
  WriteLn('Value: ', LPtr^);
  Dispose(LPtr);
  
  // Manual memory management
  GetMem(LPtr, SizeOf(Integer));
  LPtr^ := 100;
  WriteLn('Value: ', LPtr^);
  FreeMem(LPtr);
  
  // Zero-filled allocation
  LPtr := AllocMem(SizeOf(Integer));
  WriteLn('Zero-filled: ', LPtr^);
  FreeMem(LPtr);
end.

Arrays

type
  TStaticArray = array[1..10] of Integer;
  TNegativeIndex = array[-5..5] of Integer;
  TMatrix = array[1..3, 1..3] of Double;

var
  LArr: TStaticArray;
  LNeg: TNegativeIndex;
  LMatrix: TMatrix;

begin
  // Regular arrays
  LArr[5] := 100;
  
  // Negative indices work!
  LNeg[-3] := 42;
  LNeg[0] := 0;
  LNeg[3] := 42;
  
  // Multi-dimensional
  LMatrix[2, 3] := 3.14;
end.

Records

type
  TPoint = record
    X: Integer;
    Y: Integer;
  end;
  
  TPerson = record
    Name: String;
    Age: Integer;
  end;

var
  LPoint: TPoint;
  LPerson: TPerson;

begin
  LPoint.X := 10;
  LPoint.Y := 20;
  
  LPerson.Name := 'Alice';
  LPerson.Age := 30;
end.

Records map directly to C++ structs - no overhead, no translation.

Control Flow

var
  LI: Integer;

begin
  // If/then/else
  if LI > 0 then
    WriteLn('Positive')
  else if LI < 0 then
    WriteLn('Negative')
  else
    WriteLn('Zero');
  
  // For loops (to/downto)
  for LI := 1 to 10 do
    WriteLn(LI);
  
  for LI := 10 downto 1 do
    WriteLn(LI);
  
  // While loop
  while LI < 100 do
  begin
    Inc(LI);
    if LI = 50 then
      break;
  end;
  
  // Repeat/until
  repeat
    Dec(LI);
    if LI < 25 then
      continue;
    WriteLn(LI);
  until LI <= 0;
end.

Exception Handling

var
  LMsg: String;

begin
  try
    WriteLn('Before exception');
    RaiseException('Something went wrong!');
    WriteLn('After exception - not reached');
  except
    LMsg := GetExceptionMessage();
    WriteLn('Caught: ', LMsg);
  end;
  
  try
    WriteLn('In try block');
  finally
    WriteLn('Finally always executes');
  end;
end.

C++ exceptions under the hood - proper cleanup, proper unwinding.

Functions and Procedures

function Add(const A, B: Integer): Integer;
begin
  Result := A + B;
end;

procedure Swap(var A, B: Integer);
var
  LTemp: Integer;
begin
  LTemp := A;
  A := B;
  B := LTemp;
end;

function Factorial(const N: Integer): Integer;
begin
  if N <= 1 then
    Result := 1
  else
    Result := N * Factorial(N - 1);
end;

Units - Modular Programming

UnitMath.pas:

unit UnitMath;

interface

function Add(const A, B: Integer): Integer;
function Multiply(const A, B: Integer): Integer;

implementation

function Add(const A, B: Integer): Integer;
begin
  Result := A + B;
end;

function Multiply(const A, B: Integer): Integer;
begin
  Result := A * B;
end;

end.

Program.pas:

program MyApp;

uses
  UnitMath;

begin
  WriteLn('10 + 20 = ', Add(10, 20));
  WriteLn('10 * 20 = ', Multiply(10, 20));
end.

Built-in Unit Testing Framework

Professional testing built into the language:

#unittestmode on
program MathTests;

function Add(const A, B: Integer): Integer;
begin
  Result := A + B;
end;

function Multiply(const A, B: Integer): Integer;
begin
  Result := A * B;
end;

begin
  WriteLn('Main program');
end.

test 'Addition works correctly'
begin
  AssertEqual(4, Add(2, 2));
  AssertEqual(10, Add(7, 3));
  AssertEqual(-5, Add(-2, -3));
end;

test 'Multiplication works correctly'
begin
  AssertEqual(20, Multiply(4, 5));
  AssertEqual(0, Multiply(5, 0));
  AssertEqual(-15, Multiply(3, -5));
end;

Features:

  • #unittestmode on directive
  • test 'description' blocks
  • AssertEqual(expected, actual)
  • Assert(condition)
  • Integrated test runner
  • Clean output

Compiler Directives - Total Build Control

Everything configured in your Pascal source - no external build files:

program MyApp;

// Optimization
#optimization releasefast    // debug, releasesafe, releasefast, releasesmall

// Cross-compilation
#target x86_64-linux         // native, x86_64-windows, x86_64-linux, 
                              // aarch64-macos, aarch64-linux, wasm32-wasi

// Application type
#apptype gui                  // console, gui

// Search paths
#unit_path '../units'
#include_path '../include'
#library_path '../lib'

// C++ integration
#include_header '<vector>'
#include_header '"mylib.h"'
#link 'raylib'

// ABI control
#abi c                        // c, cpp

// Preprocessor
#define DEBUG
#ifdef DEBUG
  WriteLn('Debug mode');
#endif

begin
  // Your code
end.

Supported Targets:

  • native - Current platform
  • x86_64-windows - Windows 64-bit
  • x86_64-linux - Linux 64-bit
  • aarch64-macos - macOS ARM64 (Apple Silicon)
  • aarch64-linux - Linux ARM64
  • wasm32-wasi - WebAssembly (experimental)

Optimization Levels:

  • debug - Fast compile, full debug info
  • `releases...
Read more

JetPascal v0.1.0

01 Nov 20:40

Choose a tag to compare

About

JetPascal - Accelerate Your Code! 🚀 A next-generation Pascal-to-C++ transpiler that turns your Delphi/Pascal code into blazing-fast native executables. Built with a clean polymorphic architecture that emits modern C++ code, then compiles it using the Zig toolchain for cross-platform deployment.

See docs folder for details.

File Integrity

Files are signed with minisign using this public key:
RWTqBYfsUOCQscb6ZeknLC0On3cvWCVzMzlHamtgXNaDOO4bNs3WCSkV