Skip to content
 
 

Repository files navigation

Unleashed Pascal

Unleashed Pascal is a community-driven fork of Free Pascal that explores modern language features the official compiler chose not to adopt. Upstream is deliberately conservative - which has its value; this fork is where the experimental ideas get to run. Everything turns on with one line:

{$mode unleashed}

The mode is based on objfpc; every modeswitch-gated feature can also be enabled individually in objfpc / delphi via {$modeswitch X}. Backward compatibility is the one hard rule: everything is opt-in, and existing Pascal code keeps compiling untouched. The compiler always defines UNLEASHED, so a shared source tree can {$ifdef} its way between stock FPC and Unleashed; the mode itself defines FPC_UNLEASHED (and not FPC_OBJFPC).

Already sold, don't care about the tour? Yeah yeah, just scroll me straight down to the install steps.

Sixty seconds of Unleashed Pascal

A complete program. Every commented line is a separate feature, and all of them ship today.

program taste;

{$mode unleashed}

uses Classes, SysUtils;

// statement expression: if as a value
function fib(n: integer): int64;
begin
  result := if n < 2 then n else fib(n-1)+fib(n-2);
end;

// tuple return type
function minMax(const a: array of integer): (lo, hi: integer);
begin
  result := (a[0], a[0]);
  for var v in a do begin // inline loop variable
    if v < result.lo then result.lo := v;
    if v > result.hi then result.hi := v;
  end;
end;

var hits: integer;

begin
  var nums := [34, 7, 23, 32, 5, 62];              // inferred array of LongInt
  var (lo, hi) := minMax(nums);                    // tuple destructuring
  writeln($'min = {lo}, max = {hi}');              // string interpolation

  var f := async fib(32);                          // background thread, one keyword

  for parallel var i := 1 to 1000 do               // loop body across all cores
    if fib(15) = 610 then lock(hits) do hits += 1; // zero-setup critical section

  writeln($'fib(32) = {await f}, hits = {hits}');

  var log := autofree TStringList.Create;          // freed at scope exit, no finally
  log.Add($'finished at {Now:hh:nn:ss}');
  write(log.Text);
  {$ifdef WINDOWS}readln;{$endif}
end.

What is in the box

Every feature has a full reference page in unleashed/docs/ - the complete grammar, semantics, edge cases, IDE notes, and a runnable demo for each.

Concurrency without ceremony

Threads in stock Pascal mean TThread subclasses, hand-managed critical sections, and unit-level threadvar. Each collapses into a keyword.

Feature One-liner Docs
async / await var f := async work(x); ... writeln(await f); - one thread per async, one join per await async-await.md
for parallel for parallel var i := 1 to N do ... - loop body across a worker pool, with a barrier parallelfor.md
lock / trylock lock(counter) do inc(counter); - hidden critical section, auto init and release lock.md
threadstatic threadstatic next := 1000; - a per-thread variable, init once per thread thread-static.md

Write less, say more

Feature One-liner Docs
Inline Variables var x := 42; at the point of use, with type inference and block scope inline-vars.md
Statement Expressions var s := if x > 0 then 'pos' else 'neg'; - if / case / try yield values statement-expressions.md
match match cmd of 'go': run; _: skip; end; - first-match dispatch over strings, tuples, conditions match.md
Tuples function pair: (integer, integer); then var (a, b) := pair; tuples.md
String Interpolation writeln($'Hello {name}, pi = {pi:%.2f}'); string-interpolation.md
for ... step for var i := 1 to 10 step 2 do ... forstep.md
Multi-Var Init var a, b, c: integer = 42; - one initializer, independent copies multi-var-init.md
SwapValues() SwapValues(a, b); - bitwise swap, no uses, no refcount churn swapvalues.md
Type() var tmp: Type(a[0]); - static type of an expression, operand unevaluated type-intrinsic.md
128-bit Integers var x: UInt128 := 340282366920938463463374607431768211455; int128.md

Records and memory layout

Feature One-liner Docs
Composable Records embed TBase;, union ... end;, bitpacked record of byte, OffsetOf(T.field) - C-struct layout, Pascal safety composable-records.md
Flexible Array Members data: array[] of byte; as the last field - C99-style variable tail flexible-arrays.md
Static Variables static cnt: integer = 0; - program lifetime, block scope static-section.md
Scoped Cleanup defer x.Free;, var x := autofree T.Create;, with var http := autofree ... autofree.md
zeroinit procedure foo; zeroinit; - zero every local at entry zeroinit.md
Aligned Heap GetMemAligned(size, 64) and friends in system introduced-functions.md

Classes and generics

Feature One-liner Docs
Auto-Properties property Name: string; synthesizes a backing field - zero overhead auto-properties.md
Nested Generic Methods function pair<U>(...) inside TBox<T> - class and method specialize independently extra-improvements.md
Implicit Generics + Type Helpers TList<integer> without generic / specialize; type helper for integer; multiple helpers at once extra-improvements.md

Your binary, your rules

Feature One-liner Docs
Strip RTTI {$modeswitch striprtti} empties type-name strings; expose / --rttiexpose= whitelist strip-rtti.md
Custom Binary Metadata fpc --fpcsignature="" --linkerversion=14.39 --osversion=Win11 binary-metadata.md
File Embedding {$embedbytes preset 'default.bin'} bakes a file into the binary embed.md

Strings and literals

Feature One-liner Docs
Multiline Strings backtick `...` (byte-exact) and triple-quote '''...''' (auto-trimmed) multiline-strings.md
Numeric Underscores 1_000_000, $FFFFFFFF_FFFFFFFF extra-improvements.md
String-to-Ordinal Cast dword('RIFF') folds to a constant in native endianness extra-improvements.md

Quality-of-life tweaks

Semantic adjustments and small syntax unlocks - full catalog in tweaks.md and extra-improvements.md.

  • Preserved For-Loop Counter - after for i := 1 to N do ... break; the counter keeps its value.
  • is not / not in - if obj is not TFoo then, if x not in [a, b] then.
  • Compound Assignment - i div= 2;, flags xor= $05; in every mode; += and friends without {$coperators on}; both work on properties, as do inc() / dec().
  • Array Size Shorthand - array[10] of T means array[0..9] of T.
  • Array Equality - if a = b then compares two arrays element by element.
  • Indexed and Lazy Labels - label state[0..4]; goto state[n]; compiles to a case dispatch; goto done; needs no prior declaration.
  • goto, Macros, C-Operators without Directives - all implied by the mode.
  • DEBUG / RELEASE Defines - set automatically from -g: react to a debug build with {$ifdef DEBUG}, no -dDEBUG needed.

Detailed documentation

Each feature has a dedicated reference page with the full grammar, semantics, edge cases, IDE notes, and a runnable demo. Start at the index: unleashed/docs/README.md.

Unleashed IDE

For the best experience, use Unleashed Pascal IDE - a fork of the Lazarus IDE that understands unleashed mode end to end. Its parser, code completion, and Code Insight know the new syntax, so inline vars, tuples, match, async / await, and the rest autocomplete and navigate like any built-in construct, with no false-positive error markers in the editor.

Stock Lazarus still builds and runs Unleashed projects fine, but its Code Insight does not recognize the new syntax and will flag it as errors. If you stay on stock Lazarus, enable the mode through -Munleashed in the project's Custom Options rather than {$mode unleashed} in the source - that keeps the editor's background parser quieter about the constructs it cannot model.

Installation

Option 1: Official installer

Self-contained GUI installer for Windows and Linux: it downloads sources, builds the compiler and the IDE into a directory of your choice, optionally installs cross compilers, and drops a desktop shortcut wired to a per-install IDE config. No PATH changes, no registry side effects, no overwriting of an existing FPC - the whole thing lives in one folder and can be deleted by deleting that folder.

Cross targets are checkboxes: x86_64-win64, x86_64-linux, i386-win32, i386-linux, wasm32-wasip1. You can also pin the compiler and the IDE to a branch or a specific commit instead of taking the latest.

  • Repo: unleashedpascal/installer
  • Downloads: installer/releases - tagged stable releases plus a rolling nightly that tracks main
    • installer_win64_x86_64.exe - Windows host
    • installer_linux_x86_64 / installer_linux_x86_64.AppImage - Linux host

Run it, pick a directory (default C:\unleashed on Windows, $HOME/unleashed on Linux), tick the cross targets you want, click Install.

It can also build optional IDE addons in the same pass, so the editor is set up the way you like it before you write the first line - Minimap (a scaled-down view of the whole unit next to the editor), MetaDarkStyle (dark IDE theme), CPU-View (debugger plugin) and CHM help files, among others.

Re-runs are surgical: unchanged parts self-skip, a newly ticked cross target gets built, an unticked one gets removed, and toggling an addon rebuilds just the IDE. Point it at an existing install to pull an update without touching anything else.

Option 2: fpcupdeluxe

fpcupdeluxe supports Unleashed out of the box - nothing to configure. Download fpcupdeluxe, untick GitLab, and pick unleashed.git as the FPC version and the Lazarus version. From there it behaves like any regular FPC install: FPC only, Lazarus only, or both at once, with cross-compilers on the Cross tab.

In Setup+ tick Docked Lazarus IDE - the default window layout is tuned for docked mode.

fpcupdeluxe

Contributing

Unleashed Pascal is a home for innovation. If you have built a language feature that did not find a home upstream, this is where it belongs.

We are looking for new language ideas - propose modeswitches, syntax extensions, or compiler enhancements via GitHub Issues or Discussions; a well-described idea with clear use cases is valuable even without an implementation - and complete, high-quality implementations with production-grade code, test coverage, and documentation.

We are not looking for minor convenience patches, trivial reformats, or tweaks that only scratch a personal itch. Every change to a compiler carries weight; contributed code should be a meaningful feature or fix that benefits the broader community.

Releases

Contributors

Languages