English {#english}
RTL Shims: System.SysUtils and Classes
Delphi code assumes a rich runtime library: System.SysUtils for strings and conversions, System.Classes for streams and string lists. CrabPascal implements most behavior in Rust intrinsics, but Delphi projects still need .pas files to satisfy uses clauses and IDE tooling. Welcome to the shim layer under rtl/sys/.
Two-layer model
- Pascal surface — unit files with Delphi-compatible declarations
-
Rust runtime — actual implementations wired through
complete_runtime
The .pas bodies are often stubs; calls dispatch to native code:
unit System.SysUtils;
interface
function IntToStr(Value: Integer): String;
function Trim(const S: String): String;
function StrToIntDef(const S: String; Default: Integer): Integer;
implementation
function IntToStr(Value: Integer): String; begin Result := ''; end;
// Runtime intercepts and executes native IntToStr
This pattern unlocked Sprint 2 acceptance: uses System.SysUtils resolves and runs.
Namespace mapping
The unit resolver maps dotted names to filesystem paths:
System.SysUtils → rtl/sys/System.SysUtils.pas
System.Classes → rtl/sys/System.Classes.pas
System.JSON → rtl/sys/System.JSON.pas
Legacy flat units remain for older examples:
SysUtils → rtl/SysUtils.pas
uses
System.SysUtils,
System.Classes;
var
SL: TStringList;
begin
SL := TStringList.Create;
SL.Add(Trim(' hello '));
WriteLn(SL.Text);
SL.Free;
end.
System.Classes surface
Sprint 3 expanded shims for OOP-heavy code:
type
TStream = class(TObject)
function Size: Int64; virtual;
procedure Write(const Buffer: String); overload; virtual;
end;
TMemoryStream = class(TStream)
constructor Create;
end;
TStringList = class(TStrings)
procedure Add(const S: String);
property Text: String;
end;
TMemoryStream and TStringList have Rust backends — enough for JSON helpers, config files, and Horse middleware.
Generics collections
System.Generics.Collections shims declare TList<T> and TDictionary<K,V> templates. Monomorphization happens in the runtime; the Pascal file exists so generics syntax parses like Delphi:
uses System.Generics.Collections;
var
Items: TList<string>;
begin
Items := TList<string>.Create;
Items.Add('CrabPascal');
end.
What shims are not
They are not a full Delphi RTL drop-in. Missing or partial APIs should fail in check with clear messages, not crash silently. The 360° review tracks gaps: System.IOUtils, exception hierarchies, UTF-16 string semantics.
Contributing RTL coverage
Adding a function:
- Declare in the appropriate
rtl/sys/*.passhim - Implement intrinsic in Rust runtime
- Add a small
.pastest undertests/fixtures/
Keep signatures Delphi-compatible — overload sets matter.
Horse and JSON shims
HTTP examples depend on more than SysUtils. The repo includes:
rtl/Horse.pas ← HTTP framework surface
rtl/sys/System.JSON.pas ← TJSONObject, TJSONArray
rtl/sys/System.IOUtils.pas ← path helpers (partial)
Together with ProdutoService in examples/crud/, they prove the shim strategy scales beyond string utilities.
Resolver interaction
When the compiler sees uses System.Generics.Collections, unit_resolver.rs maps the dotted name to a file under rtl/sys/. Search paths from .dproj are tried first; RTL defaults apply when the unit is not in your tree. Legacy code using flat uses SysUtils, Classes still resolves via rtl/SysUtils.pas without breaking older tutorials.
Summary
Shims bridge Delphi expectations and Rust implementation. They let real projects compile with familiar uses lines while the compiler team grows native coverage sprint by sprint. Explore the tree at bitbucket.org/alphatecnologia/crabpascal under rtl/sys/.
Português {#portugus}
RTL: shims System.SysUtils e Classes
Código Delphi assume RTL rica: System.SysUtils para strings e conversões, System.Classes para streams e listas. O CrabPascal implementa a maior parte em intrinsics Rust, mas projetos Delphi ainda precisam de arquivos .pas para satisfazer uses e tooling de IDE. Entram os shims em rtl/sys/.
Modelo de duas camadas
- Superfície Pascal — units com declarações compatíveis com Delphi
-
Runtime Rust — implementações reais ligadas ao
complete_runtime
Corpos .pas são often stubs; chamadas dispatcham para código nativo:
unit System.SysUtils;
interface
function IntToStr(Value: Integer): String;
function Trim(const S: String): String;
function StrToIntDef(const S: String; Default: Integer): Integer;
implementation
function IntToStr(Value: Integer): String; begin Result := ''; end;
// Runtime intercepta e executa IntToStr nativo
Esse padrão destravou aceitação do Sprint 2: uses System.SysUtils resolve e roda.
Mapeamento de namespace
O unit resolver mapeia nomes pontuados para paths:
System.SysUtils → rtl/sys/System.SysUtils.pas
System.Classes → rtl/sys/System.Classes.pas
System.JSON → rtl/sys/System.JSON.pas
Units legadas flat permanecem para exemplos antigos:
SysUtils → rtl/SysUtils.pas
uses
System.SysUtils,
System.Classes;
var
SL: TStringList;
begin
SL := TStringList.Create;
SL.Add(Trim(' hello '));
WriteLn(SL.Text);
SL.Free;
end.
Superfície System.Classes
Sprint 3 expandiu shims para código OOP:
type
TStream = class(TObject)
function Size: Int64; virtual;
procedure Write(const Buffer: String); overload; virtual;
end;
TMemoryStream = class(TStream)
constructor Create;
end;
TStringList = class(TStrings)
procedure Add(const S: String);
property Text: String;
end;
TMemoryStream e TStringList têm backends Rust — suficiente para helpers JSON, configs e middleware Horse.
Collections genéricas
Shims System.Generics.Collections declaram templates TList<T> e TDictionary<K,V>. Monomorphização no runtime; arquivo Pascal existe para syntax de generics parsear como Delphi:
uses System.Generics.Collections;
var
Items: TList<string>;
begin
Items := TList<string>.Create;
Items.Add('CrabPascal');
end.
O que shims não são
Não são RTL Delphi completa. APIs faltantes ou parciais devem falhar no check com mensagem clara, não crash silencioso. O review 360° rastreia gaps: System.IOUtils, hierarquia de exceptions, semântica UTF-16.
Contribuindo cobertura RTL
Para adicionar função:
- Declarar no shim
rtl/sys/*.pasadequado - Implementar intrinsic no runtime Rust
- Adicionar teste
.pasemtests/fixtures/
Mantenha assinaturas compatíveis com Delphi — overloads importam.
Shims Horse e JSON
Exemplos HTTP dependem de mais que SysUtils. O repositório inclui:
rtl/Horse.pas ← superfície do framework HTTP
rtl/sys/System.JSON.pas ← TJSONObject, TJSONArray
rtl/sys/System.IOUtils.pas ← helpers de path (parcial)
Junto com ProdutoService em examples/crud/, provam que a estratégia de shim escala além de utilitários de string.
Interação com o resolver
Quando o compilador vê uses System.Generics.Collections, unit_resolver.rs mapeia o nome pontuado para arquivo em rtl/sys/. Search paths do .dproj vêm primeiro; defaults RTL aplicam quando a unit não está na sua árvore. Código legado com uses SysUtils, Classes flat ainda resolve via rtl/SysUtils.pas sem quebrar tutoriais antigos.
Resumo
Shims ligam expectativa Delphi e implementação Rust. Permitem projetos reais compilarem com uses familiares enquanto o time cresce cobertura nativa sprint a sprint. Explore em bitbucket.org/alphatecnologia/crabpascal em rtl/sys/.
Published on dev.to/@crabpascal · Código em CrabPascal
Top comments (0)